summaryrefslogtreecommitdiff
path: root/lib/ansible
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible')
-rw-r--r--lib/ansible/modules/commands/psexec.py520
-rw-r--r--lib/ansible/modules/windows/win_audit_policy_system.ps1143
-rw-r--r--lib/ansible/modules/windows/win_audit_policy_system.py73
-rw-r--r--lib/ansible/modules/windows/win_audit_rule.ps1193
-rw-r--r--lib/ansible/modules/windows/win_audit_rule.py142
-rw-r--r--lib/ansible/modules/windows/win_auto_logon.ps1403
-rw-r--r--lib/ansible/modules/windows/win_auto_logon.py77
-rw-r--r--lib/ansible/modules/windows/win_certificate_info.ps1132
-rw-r--r--lib/ansible/modules/windows/win_certificate_info.py236
-rw-r--r--lib/ansible/modules/windows/win_chocolatey.ps1803
-rw-r--r--lib/ansible/modules/windows/win_chocolatey.py385
-rw-r--r--lib/ansible/modules/windows/win_chocolatey_config.ps1122
-rw-r--r--lib/ansible/modules/windows/win_chocolatey_config.py66
-rw-r--r--lib/ansible/modules/windows/win_chocolatey_facts.ps1182
-rw-r--r--lib/ansible/modules/windows/win_chocolatey_facts.py144
-rw-r--r--lib/ansible/modules/windows/win_chocolatey_feature.ps174
-rw-r--r--lib/ansible/modules/windows/win_chocolatey_feature.py55
-rw-r--r--lib/ansible/modules/windows/win_chocolatey_source.ps1306
-rw-r--r--lib/ansible/modules/windows/win_chocolatey_source.py128
-rw-r--r--lib/ansible/modules/windows/win_computer_description.ps154
-rw-r--r--lib/ansible/modules/windows/win_computer_description.py75
-rw-r--r--lib/ansible/modules/windows/win_credential.ps1714
-rw-r--r--lib/ansible/modules/windows/win_credential.py209
-rw-r--r--lib/ansible/modules/windows/win_data_deduplication.ps1129
-rw-r--r--lib/ansible/modules/windows/win_data_deduplication.py87
-rw-r--r--lib/ansible/modules/windows/win_defrag.ps197
-rw-r--r--lib/ansible/modules/windows/win_defrag.py101
-rw-r--r--lib/ansible/modules/windows/win_disk_facts.ps1251
-rw-r--r--lib/ansible/modules/windows/win_disk_facts.py891
-rw-r--r--lib/ansible/modules/windows/win_disk_image.ps178
-rw-r--r--lib/ansible/modules/windows/win_disk_image.py67
-rw-r--r--lib/ansible/modules/windows/win_dns_record.ps1149
-rw-r--r--lib/ansible/modules/windows/win_dns_record.py131
-rw-r--r--lib/ansible/modules/windows/win_domain_computer.ps1208
-rw-r--r--lib/ansible/modules/windows/win_domain_computer.py123
-rw-r--r--lib/ansible/modules/windows/win_domain_group.ps1344
-rw-r--r--lib/ansible/modules/windows/win_domain_group.py242
-rw-r--r--lib/ansible/modules/windows/win_domain_group_membership.ps1131
-rw-r--r--lib/ansible/modules/windows/win_domain_group_membership.py130
-rw-r--r--lib/ansible/modules/windows/win_domain_object_info.ps1271
-rw-r--r--lib/ansible/modules/windows/win_domain_object_info.py162
-rw-r--r--lib/ansible/modules/windows/win_domain_user.ps1384
-rw-r--r--lib/ansible/modules/windows/win_domain_user.py376
-rw-r--r--lib/ansible/modules/windows/win_dotnet_ngen.ps161
-rw-r--r--lib/ansible/modules/windows/win_dotnet_ngen.py88
-rw-r--r--lib/ansible/modules/windows/win_eventlog.ps1287
-rw-r--r--lib/ansible/modules/windows/win_eventlog.py166
-rw-r--r--lib/ansible/modules/windows/win_eventlog_entry.ps1106
-rw-r--r--lib/ansible/modules/windows/win_eventlog_entry.py83
-rw-r--r--lib/ansible/modules/windows/win_file_compression.ps1118
-rw-r--r--lib/ansible/modules/windows/win_file_compression.py100
-rw-r--r--lib/ansible/modules/windows/win_file_version.ps163
-rw-r--r--lib/ansible/modules/windows/win_file_version.py78
-rw-r--r--lib/ansible/modules/windows/win_firewall.ps168
-rw-r--r--lib/ansible/modules/windows/win_firewall.py75
-rw-r--r--lib/ansible/modules/windows/win_firewall_rule.ps1257
-rw-r--r--lib/ansible/modules/windows/win_firewall_rule.py192
-rw-r--r--lib/ansible/modules/windows/win_format.ps1200
-rw-r--r--lib/ansible/modules/windows/win_format.py103
-rw-r--r--lib/ansible/modules/windows/win_hosts.ps1257
-rw-r--r--lib/ansible/modules/windows/win_hosts.py126
-rw-r--r--lib/ansible/modules/windows/win_hotfix.ps1239
-rw-r--r--lib/ansible/modules/windows/win_hotfix.py142
-rw-r--r--lib/ansible/modules/windows/win_http_proxy.ps1267
-rw-r--r--lib/ansible/modules/windows/win_http_proxy.py103
-rw-r--r--lib/ansible/modules/windows/win_iis_virtualdirectory.ps199
-rw-r--r--lib/ansible/modules/windows/win_iis_virtualdirectory.py75
-rw-r--r--lib/ansible/modules/windows/win_iis_webapplication.ps1138
-rw-r--r--lib/ansible/modules/windows/win_iis_webapplication.py99
-rw-r--r--lib/ansible/modules/windows/win_iis_webapppool.ps1307
-rw-r--r--lib/ansible/modules/windows/win_iis_webapppool.py211
-rw-r--r--lib/ansible/modules/windows/win_iis_webbinding.ps1377
-rw-r--r--lib/ansible/modules/windows/win_iis_webbinding.py154
-rw-r--r--lib/ansible/modules/windows/win_iis_website.ps1180
-rw-r--r--lib/ansible/modules/windows/win_iis_website.py121
-rw-r--r--lib/ansible/modules/windows/win_inet_proxy.ps1495
-rw-r--r--lib/ansible/modules/windows/win_inet_proxy.py173
-rw-r--r--lib/ansible/modules/windows/win_initialize_disk.ps1151
-rw-r--r--lib/ansible/modules/windows/win_initialize_disk.py88
-rw-r--r--lib/ansible/modules/windows/win_lineinfile.ps1450
-rw-r--r--lib/ansible/modules/windows/win_lineinfile.py180
-rw-r--r--lib/ansible/modules/windows/win_mapped_drive.ps1444
-rw-r--r--lib/ansible/modules/windows/win_mapped_drive.py155
-rw-r--r--lib/ansible/modules/windows/win_msg.ps152
-rw-r--r--lib/ansible/modules/windows/win_msg.py96
-rw-r--r--lib/ansible/modules/windows/win_netbios.ps172
-rw-r--r--lib/ansible/modules/windows/win_netbios.py80
-rw-r--r--lib/ansible/modules/windows/win_nssm.ps1498
-rw-r--r--lib/ansible/modules/windows/win_nssm.py217
-rw-r--r--lib/ansible/modules/windows/win_pagefile.ps1202
-rw-r--r--lib/ansible/modules/windows/win_pagefile.py139
-rw-r--r--lib/ansible/modules/windows/win_partition.ps1326
-rw-r--r--lib/ansible/modules/windows/win_partition.py117
-rw-r--r--lib/ansible/modules/windows/win_pester.ps1116
-rw-r--r--lib/ansible/modules/windows/win_pester.py113
-rw-r--r--lib/ansible/modules/windows/win_power_plan.ps1207
-rw-r--r--lib/ansible/modules/windows/win_power_plan.py59
-rw-r--r--lib/ansible/modules/windows/win_product_facts.ps185
-rw-r--r--lib/ansible/modules/windows/win_product_facts.py69
-rw-r--r--lib/ansible/modules/windows/win_psexec.ps1152
-rw-r--r--lib/ansible/modules/windows/win_psexec.py172
-rw-r--r--lib/ansible/modules/windows/win_psmodule.ps1468
-rw-r--r--lib/ansible/modules/windows/win_psmodule.py155
-rw-r--r--lib/ansible/modules/windows/win_psrepository.ps168
-rw-r--r--lib/ansible/modules/windows/win_psrepository.py78
-rw-r--r--lib/ansible/modules/windows/win_psrepository_info.ps168
-rw-r--r--lib/ansible/modules/windows/win_psrepository_info.py112
-rw-r--r--lib/ansible/modules/windows/win_rabbitmq_plugin.ps1157
-rw-r--r--lib/ansible/modules/windows/win_rabbitmq_plugin.py63
-rw-r--r--lib/ansible/modules/windows/win_rds_cap.ps1357
-rw-r--r--lib/ansible/modules/windows/win_rds_cap.py131
-rw-r--r--lib/ansible/modules/windows/win_rds_rap.ps1282
-rw-r--r--lib/ansible/modules/windows/win_rds_rap.py89
-rw-r--r--lib/ansible/modules/windows/win_rds_settings.ps1100
-rw-r--r--lib/ansible/modules/windows/win_rds_settings.py62
-rw-r--r--lib/ansible/modules/windows/win_region.ps1365
-rw-r--r--lib/ansible/modules/windows/win_region.py100
-rw-r--r--lib/ansible/modules/windows/win_regmerge.ps197
-rw-r--r--lib/ansible/modules/windows/win_regmerge.py82
-rw-r--r--lib/ansible/modules/windows/win_robocopy.ps1145
-rw-r--r--lib/ansible/modules/windows/win_robocopy.py147
-rw-r--r--lib/ansible/modules/windows/win_route.ps1104
-rw-r--r--lib/ansible/modules/windows/win_route.py70
-rw-r--r--lib/ansible/modules/windows/win_say.ps195
-rw-r--r--lib/ansible/modules/windows/win_say.py116
-rw-r--r--lib/ansible/modules/windows/win_scheduled_task.ps11133
-rw-r--r--lib/ansible/modules/windows/win_scheduled_task.py546
-rw-r--r--lib/ansible/modules/windows/win_scheduled_task_stat.ps1330
-rw-r--r--lib/ansible/modules/windows/win_scheduled_task_stat.py379
-rw-r--r--lib/ansible/modules/windows/win_security_policy.ps1196
-rw-r--r--lib/ansible/modules/windows/win_security_policy.py126
-rw-r--r--lib/ansible/modules/windows/win_shortcut.ps1374
-rw-r--r--lib/ansible/modules/windows/win_shortcut.py123
-rw-r--r--lib/ansible/modules/windows/win_snmp.ps1126
-rw-r--r--lib/ansible/modules/windows/win_snmp.py80
-rw-r--r--lib/ansible/modules/windows/win_timezone.ps170
-rw-r--r--lib/ansible/modules/windows/win_timezone.py68
-rw-r--r--lib/ansible/modules/windows/win_toast.ps190
-rw-r--r--lib/ansible/modules/windows/win_toast.py102
-rw-r--r--lib/ansible/modules/windows/win_unzip.ps1178
-rw-r--r--lib/ansible/modules/windows/win_unzip.py113
-rw-r--r--lib/ansible/modules/windows/win_user_profile.ps1163
-rw-r--r--lib/ansible/modules/windows/win_user_profile.py113
-rw-r--r--lib/ansible/modules/windows/win_wait_for_process.ps1176
-rw-r--r--lib/ansible/modules/windows/win_wait_for_process.py134
-rw-r--r--lib/ansible/modules/windows/win_wakeonlan.ps152
-rw-r--r--lib/ansible/modules/windows/win_wakeonlan.py62
-rw-r--r--lib/ansible/modules/windows/win_webpicmd.ps1116
-rw-r--r--lib/ansible/modules/windows/win_webpicmd.py42
-rw-r--r--lib/ansible/modules/windows/win_xml.ps1265
-rw-r--r--lib/ansible/modules/windows/win_xml.py150
-rw-r--r--lib/ansible/plugins/lookup/laps_password.py358
152 files changed, 0 insertions, 28612 deletions
diff --git a/lib/ansible/modules/commands/psexec.py b/lib/ansible/modules/commands/psexec.py
deleted file mode 100644
index 5751a64235..0000000000
--- a/lib/ansible/modules/commands/psexec.py
+++ /dev/null
@@ -1,520 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Jordan Borean <jborean93@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-
-DOCUMENTATION = r'''
----
-module: psexec
-short_description: Runs commands on a remote Windows host based on the PsExec
- model
-version_added: "2.6"
-description:
-- Runs a remote command from a Linux host to a Windows host without WinRM being
- set up.
-- Can be run on the Ansible controller to bootstrap Windows hosts to get them
- ready for WinRM.
-options:
- hostname:
- description:
- - The remote Windows host to connect to, can be either an IP address or a
- hostname.
- type: str
- required: yes
- connection_username:
- description:
- - The username to use when connecting to the remote Windows host.
- - This user must be a member of the C(Administrators) group of the Windows
- host.
- - Required if the Kerberos requirements are not installed or the username
- is a local account to the Windows host.
- - Can be omitted to use the default Kerberos principal ticket in the
- local credential cache if the Kerberos library is installed.
- - If I(process_username) is not specified, then the remote process will run
- under a Network Logon under this account.
- type: str
- connection_password:
- description:
- - The password for I(connection_user).
- - Required if the Kerberos requirements are not installed or the username
- is a local account to the Windows host.
- - Can be omitted to use a Kerberos principal ticket for the principal set
- by I(connection_user) if the Kerberos library is installed and the
- ticket has already been retrieved with the C(kinit) command before.
- type: str
- port:
- description:
- - The port that the remote SMB service is listening on.
- type: int
- default: 445
- encrypt:
- description:
- - Will use SMB encryption to encrypt the SMB messages sent to and from the
- host.
- - This requires the SMB 3 protocol which is only supported from Windows
- Server 2012 or Windows 8, older versions like Windows 7 or Windows Server
- 2008 (R2) must set this to C(no) and use no encryption.
- - When setting to C(no), the packets are in plaintext and can be seen by
- anyone sniffing the network, any process options are included in this.
- type: bool
- default: yes
- connection_timeout:
- description:
- - The timeout in seconds to wait when receiving the initial SMB negotiate
- response from the server.
- type: int
- default: 60
- executable:
- description:
- - The executable to run on the Windows host.
- type: str
- required: yes
- arguments:
- description:
- - Any arguments as a single string to use when running the executable.
- type: str
- working_directory:
- description:
- - Changes the working directory set when starting the process.
- type: str
- default: C:\Windows\System32
- asynchronous:
- description:
- - Will run the command as a detached process and the module returns
- immediately after starting the process while the process continues to
- run in the background.
- - The I(stdout) and I(stderr) return values will be null when this is set
- to C(yes).
- - The I(stdin) option does not work with this type of process.
- - The I(rc) return value is not set when this is C(yes)
- type: bool
- default: no
- load_profile:
- description:
- - Runs the remote command with the user's profile loaded.
- type: bool
- default: yes
- process_username:
- description:
- - The user to run the process as.
- - This can be set to run the process under an Interactive logon of the
- specified account which bypasses limitations of a Network logon used when
- this isn't specified.
- - If omitted then the process is run under the same account as
- I(connection_username) with a Network logon.
- - Set to C(System) to run as the builtin SYSTEM account, no password is
- required with this account.
- - If I(encrypt) is C(no), the username and password are sent as a simple
- XOR scrambled byte string that is not encrypted. No special tools are
- required to get the username and password just knowledge of the protocol.
- type: str
- process_password:
- description:
- - The password for I(process_username).
- - Required if I(process_username) is defined and not C(System).
- type: str
- integrity_level:
- description:
- - The integrity level of the process when I(process_username) is defined
- and is not equal to C(System).
- - When C(default), the default integrity level based on the system setup.
- - When C(elevated), the command will be run with Administrative rights.
- - When C(limited), the command will be forced to run with
- non-Administrative rights.
- type: str
- choices:
- - limited
- - default
- - elevated
- default: default
- interactive:
- description:
- - Will run the process as an interactive process that shows a process
- Window of the Windows session specified by I(interactive_session).
- - The I(stdout) and I(stderr) return values will be null when this is set
- to C(yes).
- - The I(stdin) option does not work with this type of process.
- type: bool
- default: no
- interactive_session:
- description:
- - The Windows session ID to use when displaying the interactive process on
- the remote Windows host.
- - This is only valid when I(interactive) is C(yes).
- - The default is C(0) which is the console session of the Windows host.
- type: int
- default: 0
- priority:
- description:
- - Set the command's priority on the Windows host.
- - See U(https://msdn.microsoft.com/en-us/library/windows/desktop/ms683211.aspx)
- for more details.
- type: str
- choices:
- - above_normal
- - below_normal
- - high
- - idle
- - normal
- - realtime
- default: normal
- show_ui_on_logon_screen:
- description:
- - Shows the process UI on the Winlogon secure desktop when
- I(process_username) is C(System).
- type: bool
- default: no
- process_timeout:
- description:
- - The timeout in seconds that is placed upon the running process.
- - A value of C(0) means no timeout.
- type: int
- default: 0
- stdin:
- description:
- - Data to send on the stdin pipe once the process has started.
- - This option has no effect when I(interactive) or I(asynchronous) is
- C(yes).
- type: str
-requirements:
-- pypsexec
-- smbprotocol[kerberos] for optional Kerberos authentication
-notes:
-- This module requires the Windows host to have SMB configured and enabled,
- and port 445 opened on the firewall.
-- This module will wait until the process is finished unless I(asynchronous)
- is C(yes), ensure the process is run as a non-interactive command to avoid
- infinite hangs waiting for input.
-- The I(connection_username) must be a member of the local Administrator group
- of the Windows host. For non-domain joined hosts, the
- C(LocalAccountTokenFilterPolicy) should be set to C(1) to ensure this works,
- see U(https://support.microsoft.com/en-us/help/951016/description-of-user-account-control-and-remote-restrictions-in-windows).
-- For more information on this module and the various host requirements, see
- U(https://github.com/jborean93/pypsexec).
-seealso:
-- module: raw
-- module: win_command
-- module: win_psexec
-- module: win_shell
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Run a cmd.exe command
- psexec:
- hostname: server
- connection_username: username
- connection_password: password
- executable: cmd.exe
- arguments: /c echo Hello World
-
-- name: Run a PowerShell command
- psexec:
- hostname: server.domain.local
- connection_username: username@DOMAIN.LOCAL
- connection_password: password
- executable: powershell.exe
- arguments: Write-Host Hello World
-
-- name: Send data through stdin
- psexec:
- hostname: 192.168.1.2
- connection_username: username
- connection_password: password
- executable: powershell.exe
- arguments: '-'
- stdin: |
- Write-Host Hello World
- Write-Error Error Message
- exit 0
-
-- name: Run the process as a different user
- psexec:
- hostname: server
- connection_user: username
- connection_password: password
- executable: whoami.exe
- arguments: /all
- process_username: anotheruser
- process_password: anotherpassword
-
-- name: Run the process asynchronously
- psexec:
- hostname: server
- connection_username: username
- connection_password: password
- executable: cmd.exe
- arguments: /c rmdir C:\temp
- asynchronous: yes
-
-- name: Use Kerberos authentication for the connection (requires smbprotocol[kerberos])
- psexec:
- hostname: host.domain.local
- connection_username: user@DOMAIN.LOCAL
- executable: C:\some\path\to\executable.exe
- arguments: /s
-
-- name: Disable encryption to work with WIndows 7/Server 2008 (R2)
- psexec:
- hostanme: windows-pc
- connection_username: Administrator
- connection_password: Password01
- encrypt: no
- integrity_level: elevated
- process_username: Administrator
- process_password: Password01
- executable: powershell.exe
- arguments: (New-Object -ComObject Microsoft.Update.Session).CreateUpdateInstaller().IsBusy
-
-- name: Download and run ConfigureRemotingForAnsible.ps1 to setup WinRM
- psexec:
- hostname: '{{ hostvars[inventory_hostname]["ansible_host"] | default(inventory_hostname) }}'
- connection_username: '{{ ansible_user }}'
- connection_password: '{{ ansible_password }}'
- encrypt: yes
- executable: powershell.exe
- arguments: '-'
- stdin: |
- $ErrorActionPreference = "Stop"
- $sec_protocols = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::SystemDefault
- $sec_protocols = $sec_protocols -bor [Net.SecurityProtocolType]::Tls12
- [Net.ServicePointManager]::SecurityProtocol = $sec_protocols
- $url = "https://github.com/ansible/ansible/raw/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
- Invoke-Expression ((New-Object Net.WebClient).DownloadString($url))
- exit
- delegate_to: localhost
-'''
-
-RETURN = r'''
-msg:
- description: Any exception details when trying to run the process
- returned: module failed
- type: str
- sample: 'Received exception from remote PAExec service: Failed to start "invalid.exe". The system cannot find the file specified. [Err=0x2, 2]'
-stdout:
- description: The stdout from the remote process
- returned: success and interactive or asynchronous is 'no'
- type: str
- sample: Hello World
-stderr:
- description: The stderr from the remote process
- returned: success and interactive or asynchronous is 'no'
- type: str
- sample: Error [10] running process
-pid:
- description: The process ID of the asynchronous process that was created
- returned: success and asynchronous is 'yes'
- type: int
- sample: 719
-rc:
- description: The return code of the remote process
- returned: success and asynchronous is 'no'
- type: int
- sample: 0
-'''
-
-import traceback
-
-from ansible.module_utils.basic import AnsibleModule, missing_required_lib
-from ansible.module_utils._text import to_bytes, to_text
-
-PYPSEXEC_IMP_ERR = None
-try:
- from pypsexec import client
- from pypsexec.exceptions import PypsexecException, PAExecException, \
- PDUException, SCMRException
- from pypsexec.paexec import ProcessPriority
- from smbprotocol.exceptions import SMBException, SMBAuthenticationError, \
- SMBResponseException
- import socket
- HAS_PYPSEXEC = True
-except ImportError:
- PYPSEXEC_IMP_ERR = traceback.format_exc()
- HAS_PYPSEXEC = False
-
-KERBEROS_IMP_ERR = None
-try:
- import gssapi
- # GSSAPI extension required for Kerberos Auth in SMB
- from gssapi.raw import inquire_sec_context_by_oid
- HAS_KERBEROS = True
-except ImportError:
- KERBEROS_IMP_ERR = traceback.format_exc()
- HAS_KERBEROS = False
-
-
-def remove_artifacts(module, client):
- try:
- client.remove_service()
- except (SMBException, PypsexecException) as exc:
- module.warn("Failed to cleanup PAExec service and executable: %s"
- % to_text(exc))
-
-
-def main():
- module_args = dict(
- hostname=dict(type='str', required=True),
- connection_username=dict(type='str'),
- connection_password=dict(type='str', no_log=True),
- port=dict(type='int', required=False, default=445),
- encrypt=dict(type='bool', default=True),
- connection_timeout=dict(type='int', default=60),
- executable=dict(type='str', required=True),
- arguments=dict(type='str'),
- working_directory=dict(type='str', default=r'C:\Windows\System32'),
- asynchronous=dict(type='bool', default=False),
- load_profile=dict(type='bool', default=True),
- process_username=dict(type='str'),
- process_password=dict(type='str', no_log=True),
- integrity_level=dict(type='str', default='default',
- choices=['default', 'elevated', 'limited']),
- interactive=dict(type='bool', default=False),
- interactive_session=dict(type='int', default=0),
- priority=dict(type='str', default='normal',
- choices=['above_normal', 'below_normal', 'high',
- 'idle', 'normal', 'realtime']),
- show_ui_on_logon_screen=dict(type='bool', default=False),
- process_timeout=dict(type='int', default=0),
- stdin=dict(type='str')
- )
- result = dict(
- changed=False,
- )
- module = AnsibleModule(
- argument_spec=module_args,
- supports_check_mode=False,
- )
-
- process_username = module.params['process_username']
- process_password = module.params['process_password']
- use_system = False
- if process_username is not None and process_username.lower() == "system":
- use_system = True
- process_username = None
- process_password = None
-
- if process_username is not None and process_password is None:
- module.fail_json(msg='parameters are required together when not '
- 'running as System: process_username, '
- 'process_password')
- if not HAS_PYPSEXEC:
- module.fail_json(msg=missing_required_lib("pypsexec"),
- exception=PYPSEXEC_IMP_ERR)
-
- hostname = module.params['hostname']
- connection_username = module.params['connection_username']
- connection_password = module.params['connection_password']
- port = module.params['port']
- encrypt = module.params['encrypt']
- connection_timeout = module.params['connection_timeout']
- executable = module.params['executable']
- arguments = module.params['arguments']
- working_directory = module.params['working_directory']
- asynchronous = module.params['asynchronous']
- load_profile = module.params['load_profile']
- elevated = module.params['integrity_level'] == "elevated"
- limited = module.params['integrity_level'] == "limited"
- interactive = module.params['interactive']
- interactive_session = module.params['interactive_session']
-
- priority = {
- "above_normal": ProcessPriority.ABOVE_NORMAL_PRIORITY_CLASS,
- "below_normal": ProcessPriority.BELOW_NORMAL_PRIORITY_CLASS,
- "high": ProcessPriority.HIGH_PRIORITY_CLASS,
- "idle": ProcessPriority.IDLE_PRIORITY_CLASS,
- "normal": ProcessPriority.NORMAL_PRIORITY_CLASS,
- "realtime": ProcessPriority.REALTIME_PRIORITY_CLASS
- }[module.params['priority']]
- show_ui_on_logon_screen = module.params['show_ui_on_logon_screen']
-
- process_timeout = module.params['process_timeout']
- stdin = module.params['stdin']
-
- if (connection_username is None or connection_password is None) and \
- not HAS_KERBEROS:
- module.fail_json(msg=missing_required_lib("gssapi"),
- execption=KERBEROS_IMP_ERR)
-
- win_client = client.Client(server=hostname, username=connection_username,
- password=connection_password, port=port,
- encrypt=encrypt)
-
- try:
- win_client.connect(timeout=connection_timeout)
- except SMBAuthenticationError as exc:
- module.fail_json(msg='Failed to authenticate over SMB: %s'
- % to_text(exc))
- except SMBResponseException as exc:
- module.fail_json(msg='Received unexpected SMB response when opening '
- 'the connection: %s' % to_text(exc))
- except PDUException as exc:
- module.fail_json(msg='Received an exception with RPC PDU message: %s'
- % to_text(exc))
- except SCMRException as exc:
- module.fail_json(msg='Received an exception when dealing with SCMR on '
- 'the Windows host: %s' % to_text(exc))
- except (SMBException, PypsexecException) as exc:
- module.fail_json(msg=to_text(exc))
- except socket.error as exc:
- module.fail_json(msg=to_text(exc))
-
- # create PAExec service and run the process
- result['changed'] = True
- b_stdin = to_bytes(stdin, encoding='utf-8') if stdin else None
- run_args = dict(
- executable=executable, arguments=arguments, asynchronous=asynchronous,
- load_profile=load_profile, interactive=interactive,
- interactive_session=interactive_session,
- run_elevated=elevated, run_limited=limited,
- username=process_username, password=process_password,
- use_system_account=use_system, working_dir=working_directory,
- priority=priority, show_ui_on_win_logon=show_ui_on_logon_screen,
- timeout_seconds=process_timeout, stdin=b_stdin
- )
- try:
- win_client.create_service()
- except (SMBException, PypsexecException) as exc:
- module.fail_json(msg='Failed to create PAExec service: %s'
- % to_text(exc))
-
- try:
- proc_result = win_client.run_executable(**run_args)
- except (SMBException, PypsexecException) as exc:
- module.fail_json(msg='Received error when running remote process: %s'
- % to_text(exc))
- finally:
- remove_artifacts(module, win_client)
-
- if asynchronous:
- result['pid'] = proc_result[2]
- elif interactive:
- result['rc'] = proc_result[2]
- else:
- result['stdout'] = proc_result[0]
- result['stderr'] = proc_result[1]
- result['rc'] = proc_result[2]
-
- # close the SMB connection
- try:
- win_client.disconnect()
- except (SMBException, PypsexecException) as exc:
- module.warn("Failed to close the SMB connection: %s" % to_text(exc))
-
- module.exit_json(**result)
-
-
-if __name__ == '__main__':
- main()
diff --git a/lib/ansible/modules/windows/win_audit_policy_system.ps1 b/lib/ansible/modules/windows/win_audit_policy_system.ps1
deleted file mode 100644
index f21e63e779..0000000000
--- a/lib/ansible/modules/windows/win_audit_policy_system.ps1
+++ /dev/null
@@ -1,143 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-
-$ErrorActionPreference = 'Stop'
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$results = @{
- changed = $false
-}
-
-######################################
-### populate sets for -validateset ###
-######################################
-$categories_rc = run-command -command 'auditpol /list /category /r'
-$subcategories_rc = run-command -command 'auditpol /list /subcategory:* /r'
-
-If ($categories_rc.item('rc') -eq 0)
-{
- $categories = ConvertFrom-Csv $categories_rc.item('stdout') | Select-Object -expand Category*
-}
-Else
-{
- Fail-Json -obj $results -message "Failed to retrive audit policy categories. Please make sure the auditpol command is functional on
- the system and that the account ansible is running under is able to retrieve them. $($_.Exception.Message)"
-}
-
-If ($subcategories_rc.item('rc') -eq 0)
-{
- $subcategories = ConvertFrom-Csv $subcategories_rc.item('stdout') | Select-Object -expand Category* |
- Where-Object {$_ -notin $categories}
-}
-Else
-{
- Fail-Json -obj $results -message "Failed to retrive audit policy subcategories. Please make sure the auditpol command is functional on
- the system and that the account ansible is running under is able to retrieve them. $($_.Exception.Message)"
-}
-
-######################
-### ansible params ###
-######################
-$category = Get-AnsibleParam -obj $params -name "category" -type "str" -ValidateSet $categories
-$subcategory = Get-AnsibleParam -obj $params -name "subcategory" -type "str" -ValidateSet $subcategories
-$audit_type = Get-AnsibleParam -obj $params -name "audit_type" -type "list" -failifempty -
-
-########################
-### Start Processing ###
-########################
-Function Get-AuditPolicy ($GetString) {
- $auditpolcsv = Run-Command -command $GetString
- If ($auditpolcsv.item('rc') -eq 0)
- {
- $Obj = ConvertFrom-CSV $auditpolcsv.item('stdout') | Select-Object @{n='subcategory';e={$_.Subcategory.ToLower()}},
- @{n='audit_type';e={$_."Inclusion Setting".ToLower()}}
- }
- Else {
- return $auditpolcsv.item('stderr')
- }
-
- $HT = @{}
- Foreach ( $Item in $Obj )
- {
- $HT.Add($Item.subcategory,$Item.audit_type)
- }
- $HT
-}
-
-################
-### Validate ###
-################
-
-#make sure category and subcategory are valid
-If (-Not $category -and -Not $subcategory) {Fail-Json -obj $results -message "You must provide either a Category or Subcategory parameter"}
-If ($category -and $subcategory) {Fail-Json -obj $results -message "Must pick either a specific subcategory or category. You cannot define both"}
-
-
-$possible_audit_types = 'success','failure','none'
-$audit_type | ForEach-Object {
- If ($_ -notin $possible_audit_types)
- {
- Fail-Json -obj $result -message "$_ is not a valid audit_type. Please choose from $($possible_audit_types -join ',')"
- }
-}
-
-#############################################################
-### build lists for setting, getting, and comparing rules ###
-#############################################################
-$audit_type_string = $audit_type -join ' and '
-
-$SetString = 'auditpol /set'
-$GetString = 'auditpol /get /r'
-
-If ($category) {$SetString = "$SetString /category:`"$category`""; $GetString = "$GetString /category:`"$category`""}
-If ($subcategory) {$SetString= "$SetString /subcategory:`"$subcategory`""; $GetString = "$GetString /subcategory:`"$subcategory`""}
-
-
-Switch ($audit_type_string)
-{
- 'success and failure' {$SetString = "$SetString /success:enable /failure:enable"; $audit_type_check = $audit_type_string}
- 'failure' {$SetString = "$SetString /success:disable /failure:enable"; $audit_type_check = $audit_type_string}
- 'success' {$SetString = "$SetString /success:enable /failure:disable"; $audit_type_check = $audit_type_string}
- 'none' {$SetString = "$SetString /success:disable /failure:disable"; $audit_type_check = 'No Auditing'}
- default {Fail-Json -obj $result -message "It seems you have specified an invalid combination of items for audit_type. Please review documentation"}
-}
-
-#########################
-### check Idempotence ###
-#########################
-
-$CurrentRule = Get-AuditPolicy $GetString
-
-#exit if the audit_type is already set properly for the category
-If (-not ($CurrentRule.Values | Where-Object {$_ -ne $audit_type_check}) )
-{
- $results.current_audit_policy = Get-AuditPolicy $GetString
- Exit-Json -obj $results
-}
-
-####################
-### Apply Change ###
-####################
-
-If (-not $check_mode)
-{
- $ApplyPolicy = Run-Command -command $SetString
-
- If ($ApplyPolicy.Item('rc') -ne 0)
- {
- $results.current_audit_policy = Get-AuditPolicy $GetString
- Fail-Json $results "Failed to set audit policy - $($_.Exception.Message)"
- }
-}
-
-$results.changed = $true
-$results.current_audit_policy = Get-AuditPolicy $GetString
-Exit-Json $results
diff --git a/lib/ansible/modules/windows/win_audit_policy_system.py b/lib/ansible/modules/windows/win_audit_policy_system.py
deleted file mode 100644
index bbcff6aad7..0000000000
--- a/lib/ansible/modules/windows/win_audit_policy_system.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_audit_policy_system
-short_description: Used to make changes to the system wide Audit Policy
-description:
- - Used to make changes to the system wide Audit Policy.
-version_added: "2.5"
-options:
- category:
- description:
- - Single string value for the category you would like to adjust the policy on.
- - Cannot be used with I(subcategory). You must define one or the other.
- - Changing this setting causes all subcategories to be adjusted to the defined I(audit_type).
- type: str
- subcategory:
- description:
- - Single string value for the subcategory you would like to adjust the policy on.
- - Cannot be used with I(category). You must define one or the other.
- type: str
- audit_type:
- description:
- - The type of event you would like to audit for.
- - Accepts a list. See examples.
- type: list
- required: yes
- choices: [ failure, none, success ]
-notes:
- - It is recommended to take a backup of the policies before adjusting them for the first time.
- - See this page for in depth information U(https://technet.microsoft.com/en-us/library/cc766468.aspx).
-seealso:
-- module: win_audit_rule
-author:
- - Noah Sparks (@nwsparks)
-'''
-
-EXAMPLES = r'''
-- name: Enable failure auditing for the subcategory "File System"
- win_audit_policy_system:
- subcategory: File System
- audit_type: failure
-
-- name: Enable all auditing types for the category "Account logon events"
- win_audit_policy_system:
- category: Account logon events
- audit_type: success, failure
-
-- name: Disable auditing for the subcategory "File System"
- win_audit_policy_system:
- subcategory: File System
- audit_type: none
-'''
-
-RETURN = r'''
-current_audit_policy:
- description: details on the policy being targetted
- returned: always
- type: dict
- sample: |-
- {
- "File Share":"failure"
- }
-'''
diff --git a/lib/ansible/modules/windows/win_audit_rule.ps1 b/lib/ansible/modules/windows/win_audit_rule.ps1
deleted file mode 100644
index 0d3ebf57b3..0000000000
--- a/lib/ansible/modules/windows/win_audit_rule.ps1
+++ /dev/null
@@ -1,193 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.SID
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-# module parameters
-$path = Get-AnsibleParam -obj $params -name "path" -type "path" -failifempty $true -aliases "destination","dest"
-$user = Get-AnsibleParam -obj $params -name "user" -type "str" -failifempty $true
-$rights = Get-AnsibleParam -obj $params -name "rights" -type "list"
-$inheritance_flags = Get-AnsibleParam -obj $params -name "inheritance_flags" -type "list" -default 'ContainerInherit','ObjectInherit'
-$propagation_flags = Get-AnsibleParam -obj $params -name "propagation_flags" -type "str" -default "none" -ValidateSet 'InheritOnly','None','NoPropagateInherit'
-$audit_flags = Get-AnsibleParam -obj $params -name "audit_flags" -type "list" -default 'success'
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset 'present','absent'
-
-#Make sure target path is valid
-If (-not (Test-Path -Path $path) )
-{
- Fail-Json -obj $result -message "defined path ($path) is not found/invalid"
-}
-
-#function get current audit rules and convert to hashtable
-Function Get-CurrentAuditRules ($path) {
- Try {
- $ACL = Get-Acl $path -Audit
- }
- Catch {
- Return "Unable to retrieve the ACL on $Path"
- }
-
- $HT = Foreach ($Obj in $ACL.Audit)
- {
- @{
- user = $Obj.IdentityReference.ToString()
- rights = ($Obj | Select-Object -expand "*rights").ToString()
- audit_flags = $Obj.AuditFlags.ToString()
- is_inherited = $Obj.IsInherited.ToString()
- inheritance_flags = $Obj.InheritanceFlags.ToString()
- propagation_flags = $Obj.PropagationFlags.ToString()
- }
- }
-
- If (-Not $HT)
- {
- "No audit rules defined on $path"
- }
- Else {$HT}
-}
-
-$result = @{
- changed = $false
- current_audit_rules = Get-CurrentAuditRules $path
-}
-
-#Make sure identity is valid and can be looked up
-Try {
- $SID = Convert-ToSid $user
-}
-Catch {
- Fail-Json -obj $result -message "Failed to lookup the identity ($user) - $($_.exception.message)"
-}
-
-#get the path type
-$ItemType = (Get-Item $path).GetType()
-switch ($ItemType)
-{
- ([Microsoft.Win32.RegistryKey]) {$registry = $true; $result.path_type = 'registry'}
- ([System.IO.FileInfo]) {$file = $true; $result.path_type = 'file'}
- ([System.IO.DirectoryInfo]) {$result.path_type = 'directory'}
-}
-
-#Get current acl/audit rules on the target
-Try {
- $ACL = Get-Acl $path -Audit
-}
-Catch {
- Fail-Json -obj $result -message "Unable to retrieve the ACL on $Path - $($_.Exception.Message)"
-}
-
-#configure acl object to remove the specified user
-If ($state -eq 'absent')
-{
- #Try and find an identity on the object that matches user
- #We skip inherited items since we can't remove those
- $ToRemove = ($ACL.Audit | Where-Object {$_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) -eq $SID -and
- $_.IsInherited -eq $false}).IdentityReference
-
- #Exit with changed false if no identity is found
- If (-Not $ToRemove)
- {
- $result.current_audit_rules = Get-CurrentAuditRules $path
- Exit-Json -obj $result
- }
-
- #update the ACL object if identity found
- Try
- {
- $ToRemove | ForEach-Object { $ACL.PurgeAuditRules($_) }
- }
- Catch
- {
- $result.current_audit_rules = Get-CurrentAuditRules $path
- Fail-Json -obj $result -message "Failed to remove audit rule: $($_.Exception.Message)"
- }
-}
-
-Else
-{
- If ($registry)
- {
- $PossibleRights = [System.Enum]::GetNames([System.Security.AccessControl.RegistryRights])
-
- Foreach ($right in $rights)
- {
- if ($right -notin $PossibleRights)
- {
- Fail-Json -obj $result -message "$right does not seem to be a valid REGISTRY right"
- }
- }
-
- $NewAccessRule = New-Object System.Security.AccessControl.RegistryAuditRule($user,$rights,$inheritance_flags,$propagation_flags,$audit_flags)
- }
- Else
- {
- $PossibleRights = [System.Enum]::GetNames([System.Security.AccessControl.FileSystemRights])
-
- Foreach ($right in $rights)
- {
- if ($right -notin $PossibleRights)
- {
- Fail-Json -obj $result -message "$right does not seem to be a valid FILE SYSTEM right"
- }
- }
-
- If ($file -and $inheritance_flags -ne 'none')
- {
- Fail-Json -obj $result -message "The target type is a file. inheritance_flags must be changed to 'none'"
- }
-
- $NewAccessRule = New-Object System.Security.AccessControl.FileSystemAuditRule($user,$rights,$inheritance_flags,$propagation_flags,$audit_flags)
- }
-
- #exit here if any existing rule matches defined rule since no change is needed
- #if we need to ignore inherited rules in the future, this would be where to do it
- #Just filter out inherited rules from $ACL.Audit
- Foreach ($group in $ACL.Audit | Where-Object {$_.IsInherited -eq $false})
- {
- If (
- ($group | Select-Object -expand "*Rights") -eq ($NewAccessRule | Select-Object -expand "*Rights") -and
- $group.AuditFlags -eq $NewAccessRule.AuditFlags -and
- $group.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) -eq $SID -and
- $group.InheritanceFlags -eq $NewAccessRule.InheritanceFlags -and
- $group.PropagationFlags -eq $NewAccessRule.PropagationFlags
- )
- {
- $result.current_audit_rules = Get-CurrentAuditRules $path
- Exit-Json -obj $result
- }
- }
-
- #try and set the acl object. AddAuditRule allows for multiple entries to exist under the same
- #identity...so if someone wanted success: write and failure: delete for example, that setup would be
- #possible. The alternative is SetAuditRule which would instead modify an existing rule and not allow
- #for setting the above example.
- Try
- {
- $ACL.AddAuditRule($NewAccessRule)
- }
- Catch
- {
- Fail-Json -obj $result -message "Failed to set the audit rule: $($_.Exception.Message)"
- }
-}
-
-
-#finally set the permissions
-Try {
- Set-Acl -Path $path -ACLObject $ACL -WhatIf:$check_mode
-}
-Catch {
- $result.current_audit_rules = Get-CurrentAuditRules $path
- Fail-Json -obj $result -message "Failed to apply audit change: $($_.Exception.Message)"
-}
-
-#exit here after a change is applied
-$result.current_audit_rules = Get-CurrentAuditRules $path
-$result.changed = $true
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_audit_rule.py b/lib/ansible/modules/windows/win_audit_rule.py
deleted file mode 100644
index d5687c120e..0000000000
--- a/lib/ansible/modules/windows/win_audit_rule.py
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_audit_rule
-short_description: Adds an audit rule to files, folders, or registry keys
-description:
- - Used to apply audit rules to files, folders or registry keys.
- - Once applied, it will begin recording the user who performed the operation defined into the Security
- Log in the Event viewer.
- - The behavior is designed to ignore inherited rules since those cannot be adjusted without first disabling
- the inheritance behavior. It will still print inherited rules in the output though for debugging purposes.
-version_added: "2.5"
-options:
- path:
- description:
- - Path to the file, folder, or registry key.
- - Registry paths should be in Powershell format, beginning with an abbreviation for the root
- such as, C(HKLM:\Software).
- type: path
- required: yes
- aliases: [ dest, destination ]
- user:
- description:
- - The user or group to adjust rules for.
- type: str
- required: yes
- rights:
- description:
- - Comma separated list of the rights desired. Only required for adding a rule.
- - If I(path) is a file or directory, rights can be any right under MSDN
- FileSystemRights U(https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemrights.aspx).
- - If I(path) is a registry key, rights can be any right under MSDN
- RegistryRights U(https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.registryrights.aspx).
- type: list
- required: yes
- inheritance_flags:
- description:
- - Defines what objects inside of a folder or registry key will inherit the settings.
- - If you are setting a rule on a file, this value has to be changed to C(none).
- - For more information on the choices see MSDN PropagationFlags enumeration
- at U(https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.inheritanceflags.aspx).
- type: list
- choices: [ ContainerInherit, ObjectInherit ]
- default: ContainerInherit,ObjectInherit
- propagation_flags:
- description:
- - Propagation flag on the audit rules.
- - This value is ignored when the path type is a file.
- - For more information on the choices see MSDN PropagationFlags enumeration
- at U(https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.propagationflags.aspx).
- choices: [ None, InherityOnly, NoPropagateInherit ]
- default: "None"
- audit_flags:
- description:
- - Defines whether to log on failure, success, or both.
- - To log both define as comma separated list "Success, Failure".
- type: list
- required: yes
- choices: [ Failure, Success ]
- state:
- description:
- - Whether the rule should be C(present) or C(absent).
- - For absent, only I(path), I(user), and I(state) are required.
- - Specifying C(absent) will remove all rules matching the defined I(user).
- type: str
- choices: [ absent, present ]
- default: present
-seealso:
-- module: win_audit_policy_system
-author:
- - Noah Sparks (@nwsparks)
-'''
-
-EXAMPLES = r'''
-- name: Add filesystem audit rule for a folder
- win_audit_rule:
- path: C:\inetpub\wwwroot\website
- user: BUILTIN\Users
- rights: write,delete,changepermissions
- audit_flags: success,failure
- inheritance_flags: ContainerInherit,ObjectInherit
-
-- name: Add filesystem audit rule for a file
- win_audit_rule:
- path: C:\inetpub\wwwroot\website\web.config
- user: BUILTIN\Users
- rights: write,delete,changepermissions
- audit_flags: success,failure
- inheritance_flags: None
-
-- name: Add registry audit rule
- win_audit_rule:
- path: HKLM:\software
- user: BUILTIN\Users
- rights: delete
- audit_flags: 'success'
-
-- name: Remove filesystem audit rule
- win_audit_rule:
- path: C:\inetpub\wwwroot\website
- user: BUILTIN\Users
- state: absent
-
-- name: Remove registry audit rule
- win_audit_rule:
- path: HKLM:\software
- user: BUILTIN\Users
- state: absent
-'''
-
-RETURN = r'''
-current_audit_rules:
- description:
- - The current rules on the defined I(path)
- - Will return "No audit rules defined on I(path)"
- returned: always
- type: dict
- sample: |
- {
- "audit_flags": "Success",
- "user": "Everyone",
- "inheritance_flags": "False",
- "is_inherited": "False",
- "propagation_flags": "None",
- "rights": "Delete"
- }
-path_type:
- description:
- - The type of I(path) being targetted.
- - Will be one of file, directory, registry.
- returned: always
- type: str
-'''
diff --git a/lib/ansible/modules/windows/win_auto_logon.ps1 b/lib/ansible/modules/windows/win_auto_logon.ps1
deleted file mode 100644
index 61b0d67f5a..0000000000
--- a/lib/ansible/modules/windows/win_auto_logon.ps1
+++ /dev/null
@@ -1,403 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Prasoon Karunan V (@prasoonkarunan) <kvprasoon@Live.in>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# All helper methods are written in a binary module and has to be loaded for consuming them.
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.AddType
-
-Set-StrictMode -Version 2.0
-
-$spec = @{
- options = @{
- logon_count = @{type = "int"}
- password = @{type = "str"; no_log = $true}
- state = @{type = "str"; choices = "absent", "present"; default = "present"}
- username = @{type = "str"}
- }
- required_if = @(
- ,@("state", "present", @("username", "password"))
- )
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$logonCount = $module.Params.logon_count
-$password = $module.Params.password
-$state = $module.Params.state
-$username = $module.Params.username
-$domain = $null
-
-if ($username) {
- # Try and get the Netlogon form of the username specified. Translating to and from a SID gives us an NTAccount
- # in the Netlogon form that we desire.
- $ntAccount = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList $username
- try {
- $accountSid = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier])
- } catch [System.Security.Principal.IdentityNotMappedException] {
- $module.FailJson("Failed to find a local or domain user with the name '$username'", $_)
- }
- $ntAccount = $accountSid.Translate([System.Security.Principal.NTAccount])
-
- $domain, $username = $ntAccount.Value -split '\\'
-}
-
-# Make sure $null regardless of any input value if state: absent
-if ($state -eq 'absent') {
- $password = $null
-}
-
-Add-CSharpType -AnsibleModule $module -References @'
-using Microsoft.Win32.SafeHandles;
-using System;
-using System.Runtime.ConstrainedExecution;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace Ansible.WinAutoLogon
-{
- internal class NativeHelpers
- {
- [StructLayout(LayoutKind.Sequential)]
- public class LSA_OBJECT_ATTRIBUTES
- {
- public UInt32 Length = 0;
- public IntPtr RootDirectory = IntPtr.Zero;
- public IntPtr ObjectName = IntPtr.Zero;
- public UInt32 Attributes = 0;
- public IntPtr SecurityDescriptor = IntPtr.Zero;
- public IntPtr SecurityQualityOfService = IntPtr.Zero;
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- internal struct LSA_UNICODE_STRING
- {
- public UInt16 Length;
- public UInt16 MaximumLength;
- public IntPtr Buffer;
-
- public static explicit operator string(LSA_UNICODE_STRING s)
- {
- byte[] strBytes = new byte[s.Length];
- Marshal.Copy(s.Buffer, strBytes, 0, s.Length);
- return Encoding.Unicode.GetString(strBytes);
- }
-
- public static SafeMemoryBuffer CreateSafeBuffer(string s)
- {
- if (s == null)
- return new SafeMemoryBuffer(IntPtr.Zero);
-
- byte[] stringBytes = Encoding.Unicode.GetBytes(s);
- int structSize = Marshal.SizeOf(typeof(LSA_UNICODE_STRING));
- IntPtr buffer = Marshal.AllocHGlobal(structSize + stringBytes.Length);
- try
- {
- LSA_UNICODE_STRING lsaString = new LSA_UNICODE_STRING()
- {
- Length = (UInt16)(stringBytes.Length),
- MaximumLength = (UInt16)(stringBytes.Length),
- Buffer = IntPtr.Add(buffer, structSize),
- };
- Marshal.StructureToPtr(lsaString, buffer, false);
- Marshal.Copy(stringBytes, 0, lsaString.Buffer, stringBytes.Length);
- return new SafeMemoryBuffer(buffer);
- }
- catch
- {
- // Make sure we free the pointer before raising the exception.
- Marshal.FreeHGlobal(buffer);
- throw;
- }
- }
- }
- }
-
- internal class NativeMethods
- {
- [DllImport("Advapi32.dll")]
- public static extern UInt32 LsaClose(
- IntPtr ObjectHandle);
-
- [DllImport("Advapi32.dll")]
- public static extern UInt32 LsaFreeMemory(
- IntPtr Buffer);
-
- [DllImport("Advapi32.dll")]
- internal static extern Int32 LsaNtStatusToWinError(
- UInt32 Status);
-
- [DllImport("Advapi32.dll")]
- public static extern UInt32 LsaOpenPolicy(
- IntPtr SystemName,
- NativeHelpers.LSA_OBJECT_ATTRIBUTES ObjectAttributes,
- LsaPolicyAccessMask AccessMask,
- out SafeLsaHandle PolicyHandle);
-
- [DllImport("Advapi32.dll")]
- public static extern UInt32 LsaRetrievePrivateData(
- SafeLsaHandle PolicyHandle,
- SafeMemoryBuffer KeyName,
- out SafeLsaMemory PrivateData);
-
- [DllImport("Advapi32.dll")]
- public static extern UInt32 LsaStorePrivateData(
- SafeLsaHandle PolicyHandle,
- SafeMemoryBuffer KeyName,
- SafeMemoryBuffer PrivateData);
- }
-
- internal class SafeLsaMemory : SafeBuffer
- {
- internal SafeLsaMemory() : base(true) { }
-
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
-
- protected override bool ReleaseHandle()
- {
- return NativeMethods.LsaFreeMemory(handle) == 0;
- }
- }
-
- internal class SafeMemoryBuffer : SafeBuffer
- {
- internal SafeMemoryBuffer() : base(true) { }
-
- internal SafeMemoryBuffer(IntPtr ptr) : base(true)
- {
- base.SetHandle(ptr);
- }
-
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
-
- protected override bool ReleaseHandle()
- {
- if (handle != IntPtr.Zero)
- Marshal.FreeHGlobal(handle);
- return true;
- }
- }
-
- public class SafeLsaHandle : SafeHandleZeroOrMinusOneIsInvalid
- {
- internal SafeLsaHandle() : base(true) { }
-
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
-
- protected override bool ReleaseHandle()
- {
- return NativeMethods.LsaClose(handle) == 0;
- }
- }
-
- public class Win32Exception : System.ComponentModel.Win32Exception
- {
- private string _exception_msg;
- public Win32Exception(string message) : this(Marshal.GetLastWin32Error(), message) { }
- public Win32Exception(int errorCode, string message) : base(errorCode)
- {
- _exception_msg = String.Format("{0} - {1} (Win32 Error Code {2}: 0x{3})", message, base.Message, errorCode, errorCode.ToString("X8"));
- }
- public override string Message { get { return _exception_msg; } }
- public static explicit operator Win32Exception(string message) { return new Win32Exception(message); }
- }
-
- [Flags]
- public enum LsaPolicyAccessMask : uint
- {
- ViewLocalInformation = 0x00000001,
- ViewAuditInformation = 0x00000002,
- GetPrivateInformation = 0x00000004,
- TrustAdmin = 0x00000008,
- CreateAccount = 0x00000010,
- CreateSecret = 0x00000020,
- CreatePrivilege = 0x00000040,
- SetDefaultQuotaLimits = 0x00000080,
- SetAuditRequirements = 0x00000100,
- AuditLogAdmin = 0x00000200,
- ServerAdmin = 0x00000400,
- LookupNames = 0x00000800,
- Read = 0x00020006,
- Write = 0x000207F8,
- Execute = 0x00020801,
- AllAccess = 0x000F0FFF,
- }
-
- public class LsaUtil
- {
- public static SafeLsaHandle OpenPolicy(LsaPolicyAccessMask access)
- {
- NativeHelpers.LSA_OBJECT_ATTRIBUTES oa = new NativeHelpers.LSA_OBJECT_ATTRIBUTES();
- SafeLsaHandle lsaHandle;
- UInt32 res = NativeMethods.LsaOpenPolicy(IntPtr.Zero, oa, access, out lsaHandle);
- if (res != 0)
- throw new Win32Exception(NativeMethods.LsaNtStatusToWinError(res),
- String.Format("LsaOpenPolicy({0}) failed", access.ToString()));
- return lsaHandle;
- }
-
- public static string RetrievePrivateData(SafeLsaHandle handle, string key)
- {
- using (SafeMemoryBuffer keyBuffer = NativeHelpers.LSA_UNICODE_STRING.CreateSafeBuffer(key))
- {
- SafeLsaMemory buffer;
- UInt32 res = NativeMethods.LsaRetrievePrivateData(handle, keyBuffer, out buffer);
- using (buffer)
- {
- if (res != 0)
- {
- // If the data object was not found we return null to indicate it isn't set.
- if (res == 0xC0000034) // STATUS_OBJECT_NAME_NOT_FOUND
- return null;
-
- throw new Win32Exception(NativeMethods.LsaNtStatusToWinError(res),
- String.Format("LsaRetrievePrivateData({0}) failed", key));
- }
-
- NativeHelpers.LSA_UNICODE_STRING lsaString = (NativeHelpers.LSA_UNICODE_STRING)
- Marshal.PtrToStructure(buffer.DangerousGetHandle(),
- typeof(NativeHelpers.LSA_UNICODE_STRING));
- return (string)lsaString;
- }
- }
- }
-
- public static void StorePrivateData(SafeLsaHandle handle, string key, string data)
- {
- using (SafeMemoryBuffer keyBuffer = NativeHelpers.LSA_UNICODE_STRING.CreateSafeBuffer(key))
- using (SafeMemoryBuffer dataBuffer = NativeHelpers.LSA_UNICODE_STRING.CreateSafeBuffer(data))
- {
- UInt32 res = NativeMethods.LsaStorePrivateData(handle, keyBuffer, dataBuffer);
- if (res != 0)
- {
- // When clearing the private data with null it may return this error which we can ignore.
- if (data == null && res == 0xC0000034) // STATUS_OBJECT_NAME_NOT_FOUND
- return;
-
- throw new Win32Exception(NativeMethods.LsaNtStatusToWinError(res),
- String.Format("LsaStorePrivateData({0}) failed", key));
- }
- }
- }
- }
-}
-'@
-
-$autoLogonRegPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon'
-$logonDetails = Get-ItemProperty -LiteralPath $autoLogonRegPath
-
-$before = @{
- state = 'absent'
-}
-if ('AutoAdminLogon' -in $logonDetails.PSObject.Properties.Name -and $logonDetails.AutoAdminLogon -eq 1) {
- $before.state = 'present'
-}
-
-$mapping = @{
- DefaultUserName = 'username'
- DefaultDomainName = 'domain'
- AutoLogonCount = 'logon_count'
-}
-foreach ($map_detail in $mapping.GetEnumerator()) {
- if ($map_detail.Key -in $logonDetails.PSObject.Properties.Name) {
- $before."$($map_detail.Value)" = $logonDetails."$($map_detail.Key)"
- }
-}
-
-$module.Diff.before = $before
-
-$propParams = @{
- LiteralPath = $autoLogonRegPath
- WhatIf = $module.CheckMode
- Force = $true
-}
-
-# First set the registry information
-# The DefaultPassword reg key should never be set, we use LSA to store the password in a more secure way.
-if ('DefaultPassword' -in (Get-Item -LiteralPath $autoLogonRegPath).Property) {
- # Bug on older Windows hosts where -WhatIf causes it fail to find the property
- if (-not $module.CheckMode) {
- Remove-ItemProperty -Name 'DefaultPassword' @propParams
- }
- $module.Result.changed = $true
-}
-
-$autoLogonKeyList = @{
- DefaultUserName = @{
- before = if ($before.ContainsKey('username')) { $before.username } else { $null }
- after = $username
- }
- DefaultDomainName = @{
- before = if ($before.ContainsKey('domain')) { $before.domain } else { $null }
- after = $domain
- }
- AutoLogonCount = @{
- before = if ($before.ContainsKey('logon_count')) { $before.logon_count } else { $null }
- after = $logonCount
- }
-}
-
-# Check AutoAdminLogon separately as it has different logic (key must exist)
-if ($state -ne $before.state) {
- $newValue = if ($state -eq 'present') { 1 } else { 0 }
- $null = New-ItemProperty -Name 'AutoAdminLogon' -Value $newValue -PropertyType DWord @propParams
- $module.Result.changed = $true
-}
-
-foreach ($key in $autoLogonKeyList.GetEnumerator()) {
- $beforeVal = $key.Value.before
- $after = $key.Value.after
-
- if ($state -eq 'present' -and $beforeVal -cne $after) {
- if ($null -ne $after) {
- $null = New-ItemProperty -Name $key.Key -Value $after @propParams
- }
- elseif (-not $module.CheckMode) {
- Remove-ItemProperty -Name $key.Key @propParams
- }
- $module.Result.changed = $true
- }
- elseif ($state -eq 'absent' -and $null -ne $beforeVal) {
- if (-not $module.CheckMode) {
- Remove-ItemProperty -Name $key.Key @propParams
- }
- $module.Result.changed = $true
- }
-}
-
-# Finally update the password in the LSA private store.
-$lsaHandle = [Ansible.WinAutoLogon.LsaUtil]::OpenPolicy('CreateSecret, GetPrivateInformation')
-try {
- $beforePass = [Ansible.WinAutoLogon.LsaUtil]::RetrievePrivateData($lsaHandle, 'DefaultPassword')
-
- if ($beforePass -cne $password) {
- # Due to .NET marshaling we need to pass in $null as NullString.Value so it's truly a null value.
- if ($null -eq $password) {
- $password = [NullString]::Value
- }
- if (-not $module.CheckMode) {
- [Ansible.WinAutoLogon.LsaUtil]::StorePrivateData($lsaHandle, 'DefaultPassword', $password)
- }
- $module.Result.changed = $true
- }
-}
-finally {
- $lsaHandle.Dispose()
-}
-
-# Need to manually craft the after diff in case we are running in check mode
-$module.Diff.after = @{
- state = $state
-}
-if ($state -eq 'present') {
- $module.Diff.after.username = $username
- $module.Diff.after.domain = $domain
- if ($null -ne $logonCount) {
- $module.Diff.after.logon_count = $logonCount
- }
-}
-
-$module.ExitJson()
-
diff --git a/lib/ansible/modules/windows/win_auto_logon.py b/lib/ansible/modules/windows/win_auto_logon.py
deleted file mode 100644
index c869361df9..0000000000
--- a/lib/ansible/modules/windows/win_auto_logon.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2019, Prasoon Karunan V (@prasoonkarunan)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_auto_logon
-short_description: Adds or Sets auto logon registry keys.
-description:
- - Used to apply auto logon registry setting.
-version_added: "2.10"
-options:
- logon_count:
- description:
- - The number of times to do an automatic logon.
- - This count is deremented by Windows everytime an automatic logon is
- performed.
- - Once the count reaches C(0) then the automatic logon process is
- disabled.
- type: int
- username:
- description:
- - Username to login automatically.
- - Must be set when C(state=present).
- - This can be the Netlogon or UPN of a domain account and is
- automatically parsed to the C(DefaultUserName) and C(DefaultDomainName)
- registry properties.
- type: str
- password:
- description:
- - Password to be used for automatic login.
- - Must be set when C(state=present).
- - Value of this input will be used as password for I(username).
- - While this value is encrypted by LSA it is decryptable to any user who
- is an Administrator on the remote host.
- type: str
- state:
- description:
- - Whether the registry key should be C(present) or C(absent).
- type: str
- choices: [ absent, present ]
- default: present
-author:
- - Prasoon Karunan V (@prasoonkarunan)
-'''
-
-EXAMPLES = r'''
-- name: Set autologon for user1
- win_auto_logon:
- username: User1
- password: str0ngp@ssword
-
-- name: Set autologon for abc.com\user1
- win_auto_logon:
- username: abc.com\User1
- password: str0ngp@ssword
-
-- name: Remove autologon for user1
- win_auto_logon:
- state: absent
-
-- name: Set autologon for user1 with a limited logon count
- win_auto_logon:
- username: User1
- password: str0ngp@ssword
- logon_count: 5
-'''
-
-RETURN = r'''
-#
-'''
diff --git a/lib/ansible/modules/windows/win_certificate_info.ps1 b/lib/ansible/modules/windows/win_certificate_info.ps1
deleted file mode 100644
index b1ff876479..0000000000
--- a/lib/ansible/modules/windows/win_certificate_info.ps1
+++ /dev/null
@@ -1,132 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Micah Hunsberger
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-function ConvertTo-Timestamp($start_date, $end_date)
-{
- if ($start_date -and $end_date)
- {
- return (New-TimeSpan -Start $start_date -End $end_date).TotalSeconds
- }
-}
-
-function Format-Date([DateTime]$date)
-{
- return $date.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssK')
-}
-
-function Get-CertificateInfo ($cert)
-{
- $epoch_date = Get-Date -Date "01/01/1970"
-
- $cert_info = @{ extensions = @() }
- $cert_info.friendly_name = $cert.FriendlyName
- $cert_info.thumbprint = $cert.Thumbprint
- $cert_info.subject = $cert.Subject
- $cert_info.issuer = $cert.Issuer
- $cert_info.valid_from = (ConvertTo-Timestamp -start_date $epoch_date -end_date $cert.NotBefore.ToUniversalTime())
- $cert_info.valid_from_iso8601 = Format-Date -date $cert.NotBefore
- $cert_info.valid_to = (ConvertTo-Timestamp -start_date $epoch_date -end_date $cert.NotAfter.ToUniversalTime())
- $cert_info.valid_to_iso8601 = Format-Date -date $cert.NotAfter
- $cert_info.serial_number = $cert.SerialNumber
- $cert_info.archived = $cert.Archived
- $cert_info.version = $cert.Version
- $cert_info.has_private_key = $cert.HasPrivateKey
- $cert_info.issued_by = $cert.GetNameInfo('SimpleName', $true)
- $cert_info.issued_to = $cert.GetNameInfo('SimpleName', $false)
- $cert_info.signature_algorithm = $cert.SignatureAlgorithm.FriendlyName
- $cert_info.dns_names = [System.Collections.Generic.List`1[String]]@($cert_info.issued_to)
- $cert_info.raw = [System.Convert]::ToBase64String($cert.GetRawCertData())
- $cert_info.public_key = [System.Convert]::ToBase64String($cert.GetPublicKey())
- if ($cert.Extensions.Count -gt 0)
- {
- [array]$cert_info.extensions = foreach ($extension in $cert.Extensions)
- {
- $extension_info = @{
- critical = $extension.Critical
- field = $extension.Oid.FriendlyName
- value = $extension.Format($false)
- }
- if ($extension -is [System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension])
- {
- $cert_info.is_ca = $extension.CertificateAuthority
- $cert_info.path_length_constraint = $extension.PathLengthConstraint
- }
- elseif ($extension -is [System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension])
- {
- $cert_info.intended_purposes = $extension.EnhancedKeyUsages.FriendlyName -as [string[]]
- }
- elseif ($extension -is [System.Security.Cryptography.X509Certificates.X509KeyUsageExtension])
- {
- $cert_info.key_usages = $extension.KeyUsages.ToString().Split(',').Trim() -as [string[]]
- }
- elseif ($extension -is [System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierExtension])
- {
- $cert_info.ski = $extension.SubjectKeyIdentifier
- }
- elseif ($extension.Oid.value -eq '2.5.29.17')
- {
- $sans = $extension.Format($true).Split("`r`n", [System.StringSplitOptions]::RemoveEmptyEntries)
- foreach ($san in $sans)
- {
- $san_parts = $san.Split("=")
- if ($san_parts.Length -ge 2 -and $san_parts[0].Trim() -eq 'DNS Name')
- {
- $cert_info.dns_names.Add($san_parts[1].Trim())
- }
- }
- }
- $extension_info
- }
- }
- return $cert_info
-}
-
-$store_location_values = ([System.Security.Cryptography.X509Certificates.StoreLocation]).GetEnumValues() | ForEach-Object { $_.ToString() }
-
-$spec = @{
- options = @{
- thumbprint = @{ type = "str"; required = $false }
- store_name = @{ type = "str"; default = "My"; }
- store_location = @{ type = "str"; default = "LocalMachine"; choices = $store_location_values; }
- }
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$thumbprint = $module.Params.thumbprint
-$store_name = $module.Params.store_name
-$store_location = [System.Security.Cryptography.X509Certificates.Storelocation]"$($module.Params.store_location)"
-
-$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
-$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
-
-$module.Result.exists = $false
-$module.Result.certificates = @()
-
-try
-{
- if ($null -ne $thumbprint)
- {
- $found_certs = $store.Certificates.Find([System.Security.Cryptography.X509Certificates.X509FindType]::FindByThumbprint, $thumbprint, $false)
- }
- else
- {
- $found_certs = $store.Certificates
- }
-
- if ($found_certs.Count -gt 0)
- {
- $module.Result.exists = $true
- [array]$module.Result.certificates = $found_certs | ForEach-Object { Get-CertificateInfo -cert $_ } | Sort-Object -Property { $_.thumbprint }
- }
-}
-finally
-{
- $store.Close()
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_certificate_info.py b/lib/ansible/modules/windows/win_certificate_info.py
deleted file mode 100644
index c8a75731ca..0000000000
--- a/lib/ansible/modules/windows/win_certificate_info.py
+++ /dev/null
@@ -1,236 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2016, Ansible, inc
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_certificate_info
-version_added: "2.10"
-short_description: Get information on certificates from a Windows Certificate Store
-description:
-- Returns information about certificates in a Windows Certificate Store.
-options:
- thumbprint:
- description:
- - The thumbprint as a hex string of a certificate to find.
- - When specified, filters the I(certificates) return value to a single certificate
- - See the examples for how to format the thumbprint.
- type: str
- required: no
- store_name:
- description:
- - The name of the store to search.
- - See U(https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.storename)
- for a list of built-in store names.
- type: str
- default: My
- store_location:
- description:
- - The location of the store to search.
- type: str
- choices: [ CurrentUser, LocalMachine ]
- default: LocalMachine
-seealso:
-- module: win_certificate_store
-author:
-- Micah Hunsberger (@mhunsber)
-'''
-
-EXAMPLES = r'''
-- name: Obtain information about a particular certificate in the computer's personal store
- win_certificate_info:
- thumbprint: BD7AF104CF1872BDB518D95C9534EA941665FD27
- register: mycert
-
-# thumbprint can also be lower case
-- name: Obtain information about a particular certificate in the computer's personal store
- win_certificate_info:
- thumbprint: bd7af104cf1872bdb518d95c9534ea941665fd27
- register: mycert
-
-- name: Obtain information about all certificates in the root store
- win_certificate_info:
- store_name: Root
- register: ca
-
-# Import a pfx and then get information on the certificates
-- name: Import pfx certificate that is password protected
- win_certificate_store:
- path: C:\Temp\cert.pfx
- state: present
- password: VeryStrongPasswordHere!
- become: yes
- become_method: runas
- register: mycert
-
-- name: Obtain information on each certificate that was touched
- win_certificate_info:
- thumbprint: "{{ item }}"
- register: mycert_stats
- loop: "{{ mycert.thumbprints }}"
-'''
-
-RETURN = r'''
-exists:
- description:
- - Whether any certificates were found in the store.
- - When I(thumbprint) is specified, returns true only if the certificate mathing the thumbprint exists.
- returned: success
- type: bool
- sample: true
-certificates:
- description:
- - A list of information about certificates found in the store, sorted by thumbprint.
- returned: success
- type: list
- elements: dict
- contains:
- archived:
- description: Indicates that the certificate is archived.
- type: bool
- sample: false
- dns_names:
- description: Lists the registered dns names for the certificate.
- type: list
- elements: str
- sample: [ '*.m.wikiquote.org', '*.wikipedia.org' ]
- extensions:
- description: The collection of the certificates extensions.
- type: list
- elements: dict
- sample: [
- {
- "critical": false,
- "field": "Subject Key Identifier",
- "value": "88 27 17 09 a9 b6 18 60 8b ec eb ba f6 47 59 c5 52 54 a3 b7"
- },
- {
- "critical": true,
- "field": "Basic Constraints",
- "value": "Subject Type=CA, Path Length Constraint=None"
- },
- {
- "critical": false,
- "field": "Authority Key Identifier",
- "value": "KeyID=2b d0 69 47 94 76 09 fe f4 6b 8d 2e 40 a6 f7 47 4d 7f 08 5e"
- },
- {
- "critical": false,
- "field": "CRL Distribution Points",
- "value": "[1]CRL Distribution Point: Distribution Point Name:Full Name:URL=http://crl.apple.com/root.crl"
- },
- {
- "critical": true,
- "field": "Key Usage",
- "value": "Digital Signature, Certificate Signing, Off-line CRL Signing, CRL Signing (86)"
- },
- {
- "critical": false,
- "field": null,
- "value": "05 00"
- }
- ]
- friendly_name:
- description: The associated alias for the certificate.
- type: str
- sample: Microsoft Root Authority
- has_private_key:
- description: Indicates that the certificate contains a private key.
- type: bool
- sample: false
- intended_purposes:
- description: lists the intended applications for the certificate.
- returned: enhanced key usages extension exists.
- type: list
- sample: [ "Server Authentication" ]
- is_ca:
- description: Indicates that the certificate is a certificate authority (CA) certificate.
- returned: basic constraints extension exists.
- type: bool
- sample: true
- issued_by:
- description: The certificate issuer's common name.
- type: str
- sample: Apple Root CA
- issued_to:
- description: The certificate's common name.
- type: str
- sample: Apple Worldwide Developer Relations Certification Authority
- issuer:
- description: The certificate issuer's distinguished name.
- type: str
- sample: 'CN=Apple Root CA, OU=Apple Certification Authority, O=Apple Inc., C=US'
- key_usages:
- description:
- - Defines how the certificate key can be used.
- - If this value is not defined, the key can be used for any purpose.
- returned: key usages extension exists.
- type: list
- elements: str
- sample: [ "CrlSign", "KeyCertSign", "DigitalSignature" ]
- path_length_constraint:
- description:
- - The number of levels allowed in a certificates path.
- - If this value is 0, the certificate does not have a restriction.
- returned: basic constraints extension exists
- type: int
- sample: 0
- public_key:
- description: The base64 encoded public key of the certificate.
- type: str
- cert_data:
- description: The base64 encoded data of the entire certificate.
- type: str
- serial_number:
- description: The serial number of the certificate represented as a hexadecimal string
- type: str
- sample: 01DEBCC4396DA010
- signature_algorithm:
- description: The algorithm used to create the certificate's signature
- type: str
- sample: sha1RSA
- ski:
- description: The certificate's subject key identifier
- returned: subject key identifier extension exists.
- type: str
- sample: 88271709A9B618608BECEBBAF64759C55254A3B7
- subject:
- description: The certificate's distinguished name.
- type: str
- sample: 'CN=Apple Worldwide Developer Relations Certification Authority, OU=Apple Worldwide Developer Relations, O=Apple Inc., C=US'
- thumbprint:
- description:
- - The thumbprint as a hex string of the certificate.
- - The return format will always be upper case.
- type: str
- sample: FF6797793A3CD798DC5B2ABEF56F73EDC9F83A64
- valid_from:
- description: The start date of the certificate represented in seconds since epoch.
- type: float
- sample: 1360255727
- valid_from_iso8601:
- description: The start date of the certificate represented as an iso8601 formatted date.
- type: str
- sample: '2017-12-15T08:39:32Z'
- valid_to:
- description: The expiry date of the certificate represented in seconds since epoch.
- type: float
- sample: 1675788527
- valid_to_iso8601:
- description: The expiry date of the certificate represented as an iso8601 formatted date.
- type: str
- sample: '2086-01-02T08:39:32Z'
- version:
- description: The x509 format version of the certificate
- type: int
- sample: 3
-'''
diff --git a/lib/ansible/modules/windows/win_chocolatey.ps1 b/lib/ansible/modules/windows/win_chocolatey.ps1
deleted file mode 100644
index d5cb87f7c0..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey.ps1
+++ /dev/null
@@ -1,803 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2014, Trond Hindenes <trond@hindenes.com>
-# Copyright: (c) 2017, Dag Wieers <dag@wieers.com>
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.ArgvParser
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-# As of chocolatey 0.9.10, non-zero success exit codes can be returned
-# See https://github.com/chocolatey/choco/issues/512#issuecomment-214284461
-$successexitcodes = (0, 1605, 1614, 1641, 3010)
-
-$spec = @{
- options = @{
- allow_empty_checksums = @{ type = "bool"; default = $false }
- allow_multiple = @{ type = "bool"; default = $false }
- allow_prerelease = @{ type = "bool"; default = $false }
- architecture = @{ type = "str"; default = "default"; choices = "default", "x86" }
- force = @{ type = "bool"; default = $false }
- ignore_checksums = @{ type = "bool"; default = $false }
- ignore_dependencies = @{ type = "bool"; default = $false }
- install_args = @{ type = "str" }
- name = @{ type = "list"; elements = "str"; required = $true }
- override_args = @{ type = "bool"; default = $false }
- package_params = @{ type = "str"; aliases = @("params") }
- pinned = @{ type = "bool" }
- proxy_url = @{ type = "str" }
- proxy_username = @{ type = "str" }
- proxy_password = @{ type = "str"; no_log = $true }
- skip_scripts = @{ type = "bool"; default = $false }
- source = @{ type = "str" }
- source_username = @{ type = "str" }
- source_password = @{ type = "str"; no_log = $true }
- state = @{ type = "str"; default = "present"; choices = "absent", "downgrade", "latest", "present", "reinstalled" }
- timeout = @{ type = "int"; default = 2700; aliases = @("execution_timeout") }
- validate_certs = @{ type = "bool"; default = $true }
- version = @{ type = "str" }
- }
- supports_check_mode = $true
-}
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$allow_empty_checksums = $module.Params.allow_empty_checksums
-$allow_multiple = $module.Params.allow_multiple
-$allow_prerelease = $module.Params.allow_prerelease
-$architecture = $module.Params.architecture
-$force = $module.Params.force
-$ignore_checksums = $module.Params.ignore_checksums
-$ignore_dependencies = $module.Params.ignore_dependencies
-$install_args = $module.Params.install_args
-$name = $module.Params.name
-$override_args = $module.Params.override_args
-$package_params = $module.Params.package_params
-$pinned = $module.Params.pinned
-$proxy_url = $module.Params.proxy_url
-$proxy_username = $module.Params.proxy_username
-$proxy_password = $module.Params.proxy_password
-$skip_scripts = $module.Params.skip_scripts
-$source = $module.Params.source
-$source_username = $module.Params.source_username
-$source_password = $module.Params.source_password
-$state = $module.Params.state
-$timeout = $module.Params.timeout
-$validate_certs = $module.Params.validate_certs
-$version = $module.Params.version
-
-$module.Result.rc = 0
-
-if (-not $validate_certs) {
- [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
-}
-
-Function Get-CommonChocolateyArguments {
- # uses global vars like check_mode and verbosity to control the common args
- # run with Chocolatey
- $arguments = [System.Collections.ArrayList]@("--yes", "--no-progress")
- # global vars that control the arguments
- if ($module.CheckMode) {
- $arguments.Add("--what-if") > $null
- }
- if ($module.Verbosity -gt 4) {
- $arguments.Add("--debug") > $null
- $arguments.Add("--verbose") > $null
- } elseif ($module.Verbosity -gt 3) {
- $arguments.Add("--verbose") > $null
- } else {
- $arguments.Add("--limit-output") > $null
- }
-
- return ,$arguments
-}
-
-Function Get-InstallChocolateyArguments {
- param(
- [bool]$allow_downgrade,
- [bool]$allow_empty_checksums,
- [bool]$allow_multiple,
- [bool]$allow_prerelease,
- [String]$architecture,
- [bool]$force,
- [bool]$ignore_dependencies,
- [String]$install_args,
- [bool]$override_args,
- [String]$package_params,
- [String]$proxy_url,
- [String]$proxy_username,
- [String]$proxy_password,
- [bool]$skip_scripts,
- [String]$source,
- [String]$source_usename,
- [String]$source_password,
- [int]$timeout,
- [String]$version
- )
- # returns an ArrayList of common arguments for install/updated a Chocolatey
- # package
- $arguments = [System.Collections.ArrayList]@("--fail-on-unfound")
- $common_args = Get-CommonChocolateyArguments
- $arguments.AddRange($common_args)
-
- if ($allow_downgrade) {
- $arguments.Add("--allow-downgrade") > $null
- }
- if ($allow_empty_checksums) {
- $arguments.Add("--allow-empty-checksums") > $null
- }
- if ($allow_multiple) {
- $arguments.Add("--allow-multiple") > $null
- }
- if ($allow_prerelease) {
- $arguments.Add("--prerelease") > $null
- }
- if ($architecture -eq "x86") {
- $arguments.Add("--x86") > $null
- }
- if ($force) {
- $arguments.Add("--force") > $null
- }
- if ($ignore_checksums) {
- $arguments.Add("--ignore-checksums") > $null
- }
- if ($ignore_dependencies) {
- $arguments.Add("--ignore-dependencies") > $null
- }
- if ($install_args) {
- $arguments.Add("--install-arguments") > $null
- $arguments.add($install_args) > $null
- }
- if ($override_args) {
- $arguments.Add("--override-arguments") > $null
- }
- if ($package_params) {
- $arguments.Add("--package-parameters") > $null
- $arguments.Add($package_params) > $null
- }
- if ($proxy_url) {
- $arguments.Add("--proxy") > $null
- $arguments.Add($proxy_url) > $null
- }
- if ($proxy_username) {
- $arguments.Add("--proxy-user") > $null
- $arguments.Add($proxy_username) > $null
- }
- if ($proxy_password) {
- $arguments.Add("--proxy-password") > $null
- $arguments.Add($proxy_password) > $null
- }
- if ($skip_scripts) {
- $arguments.Add("--skip-scripts") > $null
- }
- if ($source) {
- $arguments.Add("--source") > $null
- $arguments.Add($source) > $null
- }
- if ($source_username) {
- $arguments.Add("--user") > $null
- $arguments.Add($source_username) > $null
- $arguments.Add("--password") > $null
- $arguments.Add($source_password) > $null
- }
- if ($null -ne $timeout) {
- $arguments.Add("--timeout") > $null
- $arguments.Add($timeout) > $null
- }
- if ($version) {
- $arguments.Add("--version") > $null
- $arguments.Add($version) > $null
- }
-
- return ,$arguments
-}
-
-Function Install-Chocolatey {
- param(
- [String]$proxy_url,
- [String]$proxy_username,
- [String]$proxy_password,
- [String]$source,
- [String]$source_username,
- [String]$source_password,
- [String]$version
- )
-
- $choco_app = Get-Command -Name choco.exe -CommandType Application -ErrorAction SilentlyContinue
- if ($null -eq $choco_app) {
- # We need to install chocolatey
- # Enable TLS1.1/TLS1.2 if they're available but disabled (eg. .NET 4.5)
- $security_protocols = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::SystemDefault
- if ([Net.SecurityProtocolType].GetMember("Tls11").Count -gt 0) {
- $security_protocols = $security_protcols -bor [Net.SecurityProtocolType]::Tls11
- }
- if ([Net.SecurityProtocolType].GetMember("Tls12").Count -gt 0) {
- $security_protocols = $security_protcols -bor [Net.SecurityProtocolType]::Tls12
- }
- [Net.ServicePointManager]::SecurityProtocol = $security_protocols
-
- $client = New-Object -TypeName System.Net.WebClient
- $new_environment = @{}
- if ($proxy_url) {
- # the env values are used in the install.ps1 script when getting
- # external dependencies
- $new_environment.chocolateyProxyLocation = $proxy_url
- $web_proxy = New-Object -TypeName System.Net.WebProxy -ArgumentList $proxy_url, $true
- $client.Proxy = $web_proxy
- if ($proxy_username -and $proxy_password) {
- $new_environment.chocolateyProxyUser = $proxy_username
- $new_environment.chocolateyProxyPassword = $proxy_password
- $sec_proxy_password = ConvertTo-SecureString -String $proxy_password -AsPlainText -Force
- $web_proxy.Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $proxy_username, $sec_proxy_password
- }
- }
- if ($version) {
- # Set the chocolateyVersion environment variable when bootstrapping Chocolatey to install that specific
- # version.
- $new_environment.chocolateyVersion = $version
- }
-
- $environment = @{}
- if ($new_environment.Count -gt 0) {
- $environment = [Environment]::GetEnvironmentVariables()
- $environment += $new_environment
- }
-
- if ($source) {
- # check if the URL already contains the path to PS script
- if ($source.EndsWith(".ps1")) {
- $script_url = $source
- } else {
- # chocolatey server automatically serves a script at
- # http://host/install.ps1, we rely on this behaviour when a
- # user specifies the choco source URL. If a custom URL or file
- # path is desired, they should use win_get_url/win_shell
- # manually
- # we need to strip the path off the URL and append install.ps1
- $uri_info = [System.Uri]$source
- $script_url = "$($uri_info.Scheme)://$($uri_info.Authority)/install.ps1"
- }
- if ($source_username) {
- # while the choco-server does not require creds on install.ps1,
- # Net.WebClient will only send the credentials if the initial
- # req fails so we will add the creds in case the source URL
- # is not choco-server and requires authentication
- $sec_source_password = ConvertTo-SecureString -String $source_password -AsPlainText -Force
- $client.Credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $source_username, $sec_source_password
- }
- } else {
- $script_url = "https://chocolatey.org/install.ps1"
- }
-
- try {
- $install_script = $client.DownloadString($script_url)
- } catch {
- $module.FailJson("Failed to download Chocolatey script from '$script_url'; $($_.Exception.Message)", $_)
- }
- if (-not $module.CheckMode) {
- $res = Run-Command -command "powershell.exe -" -stdin $install_script -environment $environment
- if ($res.rc -ne 0) {
- $module.Result.rc = $res.rc
- $module.Result.stdout = $res.stdout
- $module.Result.stderr = $res.stderr
- $module.FailJson("Chocolatey bootstrap installation failed.")
- }
- $module.Warn("Chocolatey was missing from this system, so it was installed during this task run.")
- }
- $module.Result.changed = $true
-
- # locate the newly installed choco.exe
- $choco_app = Get-Command -Name choco.exe -CommandType Application -ErrorAction SilentlyContinue
- if ($null -eq $choco_app) {
- $choco_dir = $env:ChocolateyInstall
- if ($null -eq $choco_dir) {
- $choco_dir = "$env:SYSTEMDRIVE\ProgramData\Chocolatey"
- }
- $choco_app = Get-Command -Name "$choco_dir\bin\choco.exe" -CommandType Application -ErrorAction SilentlyContinue
- }
- }
-
- if ($module.CheckMode -and $null -eq $choco_app) {
- $module.Result.skipped = $true
- $module.Result.msg = "Skipped check mode run on win_chocolatey as choco.exe cannot be found on the system"
- $module.ExitJson()
- }
-
- if ($null -eq $choco_app -or -not (Test-Path -LiteralPath $choco_app.Path)) {
- $module.FailJson("Failed to find choco.exe, make sure it is added to the PATH or the env var 'ChocolateyInstall' is set")
- }
-
- $actual_version = (Get-ChocolateyPackageVersion -choco_path $choco_app.Path -name chocolatey)[0]
- try {
- # The Chocolatey version may not be in the strict form of major.minor.build and will fail to cast to
- # System.Version. We want to warn if this is the case saying module behaviour may be incorrect.
- $actual_version = [Version]$actual_version
- } catch {
- $module.Warn("Failed to parse Chocolatey version '$actual_version' for checking module requirements, module may not work correctly: $($_.Exception.Message)")
- $actual_version = $null
- }
- if ($null -ne $actual_version -and $actual_version -lt [Version]"0.10.5") {
- if ($module.CheckMode) {
- $module.Result.skipped = $true
- $module.Result.msg = "Skipped check mode run on win_chocolatey as choco.exe is too old, a real run would have upgraded the executable. Actual: '$actual_version', Minimum Version: '0.10.5'"
- $module.ExitJson()
- }
- $module.Warn("Chocolatey was older than v0.10.5 so it was upgraded during this task run.")
- Update-ChocolateyPackage -choco_path $choco_app.Path -packages @("chocolatey") `
-
- -proxy_url $proxy_url -proxy_username $proxy_username `
- -proxy_password $proxy_password -source $source `
- -source_username $source_username -source_password $source_password
- }
-
- return $choco_app.Path
-}
-
-Function Get-ChocolateyPackageVersion {
- Param (
- [Parameter(Mandatory=$true)]
- [System.String]
- $choco_path,
-
- [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
- [System.String]
- $name
- )
-
- Begin {
- # Due to https://github.com/chocolatey/choco/issues/1843, we get a list of all the installed packages and
- # filter it ourselves. This has the added benefit of being quicker when dealing with multiple packages as we
- # only call choco.exe once.
- $command = Argv-ToString -arguments @($choco_path, 'list', '--local-only', '--limit-output', '--all-versions')
- $res = Run-Command -command $command
-
- # Chocolatey v0.10.12 introduced enhanced exit codes, 2 means no results, e.g. no package
- if ($res.rc -notin @(0, 2)) {
- $module.Result.command = $command
- $module.Result.rc = $res.rc
- $module.Result.stdout = $res.stdout
- $module.Result.stderr = $res.stderr
- $module.FailJson('Error checking installation status for chocolatey packages')
- }
-
- # Parse the stdout to get a list of all packages installed and their versions.
- $installed_packages = $res.stdout.Trim().Split([System.Environment]::NewLine) | ForEach-Object -Process {
- if ($_.Contains('|')) { # Sanity in case further output is added in the future.
- $package_split = $_.Split('|', 2)
- @{ Name = $package_split[0]; Version = $package_split[1] }
- }
- }
-
- # Create a hashtable that will store our package version info.
- $installed_info = @{}
- }
-
- Process {
- if ($name -eq 'all') {
- # All is a special package name that means all installed packages, we set a dummy version so absent, latest
- # and downgrade will run with all.
- $installed_info.'all' = @('0.0.0')
- } else {
- $package_info = $installed_packages | Where-Object { $_.Name -eq $name }
- if ($null -eq $package_info) {
- $installed_info.$name = $null
- } else {
- $installed_info.$name = @($package_info.Version)
- }
- }
- }
-
- End {
- return $installed_info
- }
-}
-
-Function Get-ChocolateyPin {
- param(
- [Parameter(Mandatory=$true)][String]$choco_path
- )
-
- $command = Argv-ToString -arguments @($choco_path, "pin", "list", "--limit-output")
- $res = Run-Command -command $command
- if ($res.rc -ne 0) {
- $module.Result.command = $command
- $module.Result.rc = $res.rc
- $module.Result.stdout = $res.stdout
- $module.Result.stderr = $res.stderr
- $module.FailJson("Error getting list of pinned packages")
- }
-
- $stdout = $res.stdout.Trim()
- $pins = @{}
-
- $stdout.Split("`r`n", [System.StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object {
- $package = $_.Substring(0, $_.LastIndexOf("|"))
- $version = $_.Substring($_.LastIndexOf("|") + 1)
-
- if ($pins.ContainsKey($package)) {
- $pinned_versions = $pins.$package
- } else {
- $pinned_versions = [System.Collections.Generic.List`1[String]]@()
- }
- $pinned_versions.Add($version)
- $pins.$package = $pinned_versions
- }
- return ,$pins
-}
-
-Function Set-ChocolateyPin {
- param(
- [Parameter(Mandatory=$true)][String]$choco_path,
- [Parameter(Mandatory=$true)][String]$name,
- [Switch]$pin,
- [String]$version
- )
- if ($pin) {
- $action = "add"
- $err_msg = "Error pinning package '$name'"
- } else {
- $action = "remove"
- $err_msg = "Error unpinning package '$name'"
- }
-
- $arguments = [System.Collections.ArrayList]@($choco_path, "pin", $action, "--name", $name)
- if ($version) {
- $err_msg += " at '$version'"
- $arguments.Add("--version") > $null
- $arguments.Add($version) > $null
- }
- $common_args = Get-CommonChocolateyArguments
- $arguments.AddRange($common_args)
-
- $command = Argv-ToString -arguments $arguments
- $res = Run-Command -command $command
- if ($res.rc -ne 0) {
- $module.Result.command = $command
- $module.Result.rc = $res.rc
- $module.Result.stdout = $res.stdout
- $module.Result.stderr = $res.stderr
- $module.FailJson($err_msg)
- }
- $module.result.changed = $true
-}
-
-Function Update-ChocolateyPackage {
- param(
- [Parameter(Mandatory=$true)][String]$choco_path,
- [Parameter(Mandatory=$true)][String[]]$packages,
- [bool]$allow_downgrade,
- [bool]$allow_empty_checksums,
- [bool]$allow_multiple,
- [bool]$allow_prerelease,
- [String]$architecture,
- [bool]$force,
- [bool]$ignore_checksums,
- [bool]$ignore_dependencies,
- [String]$install_args,
- [bool]$override_args,
- [String]$package_params,
- [String]$proxy_url,
- [String]$proxy_username,
- [String]$proxy_password,
- [bool]$skip_scripts,
- [String]$source,
- [String]$source_username,
- [String]$source_password,
- [int]$timeout,
- [String]$version
- )
-
- $arguments = [System.Collections.ArrayList]@($choco_path, "upgrade")
- $arguments.AddRange($packages)
-
- $common_params = @{
- allow_downgrade = $allow_downgrade
- allow_empty_checksums = $allow_empty_checksums
- allow_multiple = $allow_multiple
- allow_prerelease = $allow_prerelease
- architecture = $architecture
- force = $force
- ignore_checksums = $ignore_checksums
- ignore_dependencies = $ignore_dependencies
- install_args = $install_args
- override_args = $override_args
- package_params = $package_params
- proxy_url = $proxy_url
- proxy_username = $proxy_username
- proxy_password = $proxy_password
- skip_scripts = $skip_scripts
- source = $source
- source_username = $source_username
- source_password = $source_password
- timeout = $timeout
- version = $version
- }
- $common_args = Get-InstallChocolateyArguments @common_params
- $arguments.AddRange($common_args)
-
- $command = Argv-ToString -arguments $arguments
- $res = Run-Command -command $command
- $module.Result.rc = $res.rc
- if ($res.rc -notin $successexitcodes) {
- $module.Result.command = $command
- $module.Result.stdout = $res.stdout
- $module.Result.stderr = $res.stderr
- $module.FailJson("Error updating package(s) '$($packages -join ", ")'")
- }
-
- if ($module.Verbosity -gt 1) {
- $module.Result.stdout = $res.stdout
- }
-
- if ($res.stdout -match ' upgraded (\d+)/\d+ package') {
- if ($Matches[1] -gt 0) {
- $module.Result.changed = $true
- }
- }
- # need to set to false in case the rc is not 0 and a failure didn't actually occur
- $module.Result.failed = $false
-}
-
-Function Install-ChocolateyPackage {
- param(
- [Parameter(Mandatory=$true)][String]$choco_path,
- [Parameter(Mandatory=$true)][String[]]$packages,
- [bool]$allow_downgrade,
- [bool]$allow_empty_checksums,
- [bool]$allow_multiple,
- [bool]$allow_prerelease,
- [String]$architecture,
- [bool]$force,
- [bool]$ignore_checksums,
- [bool]$ignore_dependencies,
- [String]$install_args,
- [bool]$override_args,
- [String]$package_params,
- [String]$proxy_url,
- [String]$proxy_username,
- [String]$proxy_password,
- [bool]$skip_scripts,
- [String]$source,
- [String]$source_username,
- [String]$source_password,
- [int]$timeout,
- [String]$version
- )
-
- $arguments = [System.Collections.ArrayList]@($choco_path, "install")
- $arguments.AddRange($packages)
- $common_params = @{
- allow_downgrade = $allow_downgrade
- allow_empty_checksums = $allow_empty_checksums
- allow_multiple = $allow_multiple
- allow_prerelease = $allow_prerelease
- architecture = $architecture
- force = $force
- ignore_checksums = $ignore_checksums
- ignore_dependencies = $ignore_dependencies
- install_args = $install_args
- override_args = $override_args
- package_params = $package_params
- proxy_url = $proxy_url
- proxy_username = $proxy_username
- proxy_password = $proxy_password
- skip_scripts = $skip_scripts
- source = $source
- source_username = $source_username
- source_password = $source_password
- timeout = $timeout
- version = $version
- }
- $common_args = Get-InstallChocolateyArguments @common_params
- $arguments.AddRange($common_args)
-
- $command = Argv-ToString -arguments $arguments
- $res = Run-Command -command $command
- $module.Result.rc = $res.rc
- if ($res.rc -notin $successexitcodes) {
- $module.Result.command = $command
- $module.Result.stdout = $res.stdout
- $module.Result.stderr = $res.stderr
- $module.FailJson("Error installing package(s) '$($packages -join ', ')'")
- }
-
- if ($module.Verbosity -gt 1) {
- $module.Result.stdout = $res.stdout
- }
-
- $module.Result.changed = $true
- # need to set to false in case the rc is not 0 and a failure didn't actually occur
- $module.Result.failed = $false
-}
-
-Function Uninstall-ChocolateyPackage {
- param(
- [Parameter(Mandatory=$true)][String]$choco_path,
- [Parameter(Mandatory=$true)][String[]]$packages,
- [bool]$force,
- [String]$package_params,
- [bool]$skip_scripts,
- [int]$timeout,
- [String]$version
- )
-
- $arguments = [System.Collections.ArrayList]@($choco_path, "uninstall")
- $arguments.AddRange($packages)
- $common_args = Get-CommonChocolateyArguments
- $arguments.AddRange($common_args)
-
- if ($force) {
- $arguments.Add("--force") > $null
- }
- if ($package_params) {
- $arguments.Add("--package-params") > $null
- $arguments.Add($package_params) > $null
- }
- if ($skip_scripts) {
- $arguments.Add("--skip-scripts") > $null
- }
- if ($null -ne $timeout) {
- $arguments.Add("--timeout") > $null
- $arguments.Add($timeout) > $null
- }
- if ($version) {
- # Need to set allow-multiple to make sure choco doesn't uninstall all versions
- $arguments.Add("--allow-multiple") > $null
- $arguments.Add("--version") > $null
- $arguments.Add($version) > $null
- } else {
- $arguments.Add("--all-versions") > $null
- }
-
- $command = Argv-ToString -arguments $arguments
- $res = Run-Command -command $command
- $module.Result.rc = $res.rc
- if ($res.rc -notin $successexitcodes) {
- $module.Result.command = $command
- $module.Result.stdout = $res.stdout
- $module.Result.stderr = $res.stderr
- $module.FailJson("Error uninstalling package(s) '$($packages -join ", ")'")
- }
-
- if ($module.Verbosity -gt 1) {
- $module.Result.stdout = $res.stdout
- }
- $module.Result.changed = $true
- # need to set to false in case the rc is not 0 and a failure didn't actually occur
- $module.Result.failed = $false
-}
-
-# get the full path to choco.exe, otherwise install/upgrade to at least 0.10.5
-$install_params = @{
- proxy_url = $proxy_url
- proxy_username = $proxy_username
- proxy_password = $proxy_password
- source = $source
- source_username = $source_username
- source_password = $source_password
-}
-if ($version -and "chocolatey" -in $name) {
- # If a version is set and chocolatey is in the package list, pass the chocolatey version to the bootstrapping
- # process.
- $install_params.version = $version
-}
-$choco_path = Install-Chocolatey @install_params
-
-if ('all' -in $name -and $state -in @('present', 'reinstalled')) {
- $module.FailJson("Cannot specify the package name as 'all' when state=$state")
-}
-
-# get the version of all specified packages
-$package_info = $name | Get-ChocolateyPackageVersion -choco_path $choco_path
-
-if ($state -in "absent", "reinstalled") {
- $installed_packages = ($package_info.GetEnumerator() | Where-Object { $null -ne $_.Value }).Key
- if ($null -ne $installed_packages) {
- Uninstall-ChocolateyPackage -choco_path $choco_path -packages $installed_packages `
- -force $force -package_params $package_params -skip_scripts $skip_scripts `
- -timeout $timeout -version $version
- }
-
- # ensure the package info for the uninstalled versions has been removed
- # so state=reinstall will install them in the next step
- foreach ($package in $installed_packages) {
- $package_info.$package = $null
- }
-}
-
-if ($state -in @("downgrade", "latest", "present", "reinstalled")) {
- if ($state -eq "present" -and $force) {
- # when present and force, we just run the install step with the packages specified
- $missing_packages = $name
- } else {
- # otherwise only install the packages that are not installed
- $missing_packages = [System.Collections.ArrayList]@()
- foreach ($package in $package_info.GetEnumerator()) {
- if ($null -eq $package.Value) {
- $missing_packages.Add($package.Key) > $null
- }
- }
- }
-
- # if version is specified and installed version does not match or not
- # allow_multiple, throw error ignore this if force is set
- if ($state -eq "present" -and $null -ne $version -and -not $force) {
- foreach ($package in $name) {
- $package_versions = [System.Collections.ArrayList]$package_info.$package
- if ($package_versions.Count -gt 0) {
- if (-not $package_versions.Contains($version) -and -not $allow_multiple) {
- $module.FailJson("Chocolatey package '$package' is already installed with version(s) '$($package_versions -join "', '")' but was expecting '$version'. Either change the expected version, set state=latest, set allow_multiple=yes, or set force=yes to continue")
- } elseif ($version -notin $package_versions -and $allow_multiple) {
- # add the package back into the list of missing packages if installing multiple
- $missing_packages.Add($package) > $null
- }
- }
- }
- }
- $common_args = @{
- choco_path = $choco_path
- allow_downgrade = ($state -eq "downgrade")
- allow_empty_checksums = $allow_empty_checksums
- allow_multiple = $allow_multiple
- allow_prerelease = $allow_prerelease
- architecture = $architecture
- force = $force
- ignore_checksums = $ignore_checksums
- ignore_dependencies = $ignore_dependencies
- install_args = $install_args
- override_args = $override_args
- package_params = $package_params
- proxy_url = $proxy_url
- proxy_username = $proxy_username
- proxy_password = $proxy_password
- skip_scripts = $skip_scripts
- source = $source
- source_username = $source_username
- source_password = $source_password
- timeout = $timeout
- version = $version
- }
-
- if ($missing_packages) {
- Install-ChocolateyPackage -packages $missing_packages @common_args
- }
-
- if ($state -eq "latest" -or ($state -eq "downgrade" -and $null -ne $version)) {
- # when in a downgrade/latest situation, we want to run choco upgrade on
- # the remaining packages that were already installed, don't run this if
- # state=downgrade and a version isn't specified (this will actually
- # upgrade a package)
- $installed_packages = ($package_info.GetEnumerator() | Where-Object { $null -ne $_.Value }).Key
- if ($null -ne $installed_packages) {
- Update-ChocolateyPackage -packages $installed_packages @common_args
- }
- }
-
- # Now we want to pin/unpin any packages now that it has been installed/upgraded
- if ($null -ne $pinned) {
- $pins = Get-ChocolateyPin -choco_path $choco_path
-
- foreach ($package in $name) {
- if ($pins.ContainsKey($package)) {
- if (-not $pinned -and $null -eq $version) {
- # No version is set and pinned=no, we want to remove all pins on the package. There is a bug in
- # 'choco pin remove' with multiple versions where an older version might be pinned but
- # 'choco pin remove' will still fail without an explicit version. Instead we take the literal
- # interpretation that pinned=no and no version means the package has no pins at all
- foreach ($v in $pins.$package) {
- Set-ChocolateyPin -choco_path $choco_path -name $package -version $v
- }
- } elseif ($null -ne $version -and $pins.$package.Contains($version) -ne $pinned) {
- Set-ChocolateyPin -choco_path $choco_path -name $package -pin:$pinned -version $version
- }
- } elseif ($pinned) {
- # Package had no pins but pinned=yes is set.
- Set-ChocolateyPin -choco_path $choco_path -name $package -pin -version $version
- }
- }
- }
-}
-
-$module.ExitJson()
-
diff --git a/lib/ansible/modules/windows/win_chocolatey.py b/lib/ansible/modules/windows/win_chocolatey.py
deleted file mode 100644
index 6792f59a93..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey.py
+++ /dev/null
@@ -1,385 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2014, Trond Hindenes <trond@hindenes.com>
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_chocolatey
-version_added: '1.9'
-short_description: Manage packages using chocolatey
-description:
-- Manage packages using Chocolatey.
-- If Chocolatey is missing from the system, the module will install it.
-requirements:
-- chocolatey >= 0.10.5 (will be upgraded if older)
-options:
- allow_empty_checksums:
- description:
- - Allow empty checksums to be used for downloaded resource from non-secure
- locations.
- - Use M(win_chocolatey_feature) with the name C(allowEmptyChecksums) to
- control this option globally.
- type: bool
- default: no
- version_added: '2.2'
- allow_multiple:
- description:
- - Allow the installation of multiple packages when I(version) is specified.
- - Having multiple packages at different versions can cause issues if the
- package doesn't support this. Use at your own risk.
- type: bool
- default: no
- version_added: '2.8'
- allow_prerelease:
- description:
- - Allow the installation of pre-release packages.
- - If I(state) is C(latest), the latest pre-release package will be
- installed.
- type: bool
- default: no
- version_added: '2.6'
- architecture:
- description:
- - Force Chocolatey to install the package of a specific process
- architecture.
- - When setting C(x86), will ensure Chocolatey installs the x86 package
- even when on an x64 bit OS.
- type: str
- choices: [ default, x86 ]
- default: default
- version_added: '2.7'
- force:
- description:
- - Forces the install of a package, even if it already is installed.
- - Using I(force) will cause Ansible to always report that a change was
- made.
- type: bool
- default: no
- ignore_checksums:
- description:
- - Ignore the checksums provided by the package.
- - Use M(win_chocolatey_feature) with the name C(checksumFiles) to control
- this option globally.
- type: bool
- default: no
- version_added: '2.2'
- ignore_dependencies:
- description:
- - Ignore dependencies, only install/upgrade the package itself.
- type: bool
- default: no
- version_added: '2.1'
- install_args:
- description:
- - Arguments to pass to the native installer.
- - These are arguments that are passed directly to the installer the
- Chocolatey package runs, this is generally an advanced option.
- type: str
- version_added: '2.1'
- name:
- description:
- - Name of the package(s) to be installed.
- - Set to C(all) to run the action on all the installed packages.
- type: list
- required: yes
- override_args:
- description:
- - Override arguments of native installer with arguments provided by user.
- - Should install arguments be used exclusively without appending
- to current package passed arguments.
- type: bool
- version_added: '2.10'
- package_params:
- description:
- - Parameters to pass to the package.
- - These are parameters specific to the Chocolatey package and are generally
- documented by the package itself.
- - Before Ansible 2.7, this option was just I(params).
- type: str
- version_added: '2.1'
- aliases: [ params ]
- pinned:
- description:
- - Whether to pin the Chocolatey package or not.
- - If omitted then no checks on package pins are done.
- - Will pin/unpin the specific version if I(version) is set.
- - Will pin the latest version of a package if C(yes), I(version) is not set
- and and no pin already exists.
- - Will unpin all versions of a package if C(no) and I(version) is not set.
- - This is ignored when C(state=absent).
- type: bool
- version_added: '2.8'
- proxy_url:
- description:
- - Proxy URL used to install chocolatey and the package.
- - Use M(win_chocolatey_config) with the name C(proxy) to control this
- option globally.
- type: str
- version_added: '2.4'
- proxy_username:
- description:
- - Proxy username used to install Chocolatey and the package.
- - Before Ansible 2.7, users with double quote characters C(") would need to
- be escaped with C(\) beforehand. This is no longer necessary.
- - Use M(win_chocolatey_config) with the name C(proxyUser) to control this
- option globally.
- type: str
- version_added: '2.4'
- proxy_password:
- description:
- - Proxy password used to install Chocolatey and the package.
- - This value is exposed as a command argument and any privileged account
- can see this value when the module is running Chocolatey, define the
- password on the global config level with M(win_chocolatey_config) with
- name C(proxyPassword) to avoid this.
- type: str
- version_added: '2.4'
- skip_scripts:
- description:
- - Do not run I(chocolateyInstall.ps1) or I(chocolateyUninstall.ps1) scripts
- when installing a package.
- type: bool
- default: no
- version_added: '2.4'
- source:
- description:
- - Specify the source to retrieve the package from.
- - Use M(win_chocolatey_source) to manage global sources.
- - This value can either be the URL to a Chocolatey feed, a path to a folder
- containing C(.nupkg) packages or the name of a source defined by
- M(win_chocolatey_source).
- - This value is also used when Chocolatey is not installed as the location
- of the install.ps1 script and only supports URLs for this case.
- type: str
- source_username:
- description:
- - A username to use with I(source) when accessing a feed that requires
- authentication.
- - It is recommended you define the credentials on a source with
- M(win_chocolatey_source) instead of passing it per task.
- type: str
- version_added: '2.7'
- source_password:
- description:
- - The password for I(source_username).
- - This value is exposed as a command argument and any privileged account
- can see this value when the module is running Chocolatey, define the
- credentials with a source with M(win_chocolatey_source) to avoid this.
- type: str
- version_added: '2.7'
- state:
- description:
- - State of the package on the system.
- - When C(absent), will ensure the package is not installed.
- - When C(present), will ensure the package is installed.
- - When C(downgrade), will allow Chocolatey to downgrade a package if
- I(version) is older than the installed version.
- - When C(latest), will ensure the package is installed to the latest
- available version.
- - When C(reinstalled), will uninstall and reinstall the package.
- type: str
- choices: [ absent, downgrade, latest, present, reinstalled ]
- default: present
- timeout:
- description:
- - The time to allow chocolatey to finish before timing out.
- type: int
- default: 2700
- version_added: '2.3'
- aliases: [ execution_timeout ]
- validate_certs:
- description:
- - Used when downloading the Chocolatey install script if Chocolatey is not
- already installed, this does not affect the Chocolatey package install
- process.
- - When C(no), no SSL certificates will be validated.
- - This should only be used on personally controlled sites using self-signed
- certificate.
- type: bool
- default: yes
- version_added: '2.7'
- version:
- description:
- - Specific version of the package to be installed.
- - When I(state) is set to C(absent), will uninstall the specific version
- otherwise all versions of that package will be removed.
- - If a different version of package is installed, I(state) must be C(latest)
- or I(force) set to C(yes) to install the desired version.
- - Provide as a string (e.g. C('6.1')), otherwise it is considered to be
- a floating-point number and depending on the locale could become C(6,1),
- which will cause a failure.
- - If I(name) is set to C(chocolatey) and Chocolatey is not installed on the
- host, this will be the version of Chocolatey that is installed. You can
- also set the C(chocolateyVersion) environment var.
- type: str
-notes:
-- This module will install or upgrade Chocolatey when needed.
-- When using verbosity 2 or less (C(-vv)) the C(stdout) output will be restricted.
- When using verbosity 4 (C(-vvvv)) the C(stdout) output will be more verbose.
- When using verbosity 5 (C(-vvvvv)) the C(stdout) output will include debug output.
-- Some packages, like hotfixes or updates need an interactive user logon in
- order to install. You can use C(become) to achieve this, see
- :ref:`become_windows`.
- Even if you are connecting as local Administrator, using C(become) to
- become Administrator will give you an interactive user logon, see examples
- below.
-- If C(become) is unavailable, use M(win_hotfix) to install hotfixes instead
- of M(win_chocolatey) as M(win_hotfix) avoids using C(wusa.exe) which cannot
- be run without C(become).
-seealso:
-- module: win_chocolatey_config
-- module: win_chocolatey_facts
-- module: win_chocolatey_feature
-- module: win_chocolatey_source
-- module: win_feature
-- module: win_hotfix
- description: Use when C(become) is unavailable, to avoid using C(wusa.exe).
-- module: win_package
-- module: win_updates
-- name: Chocolatey website
- description: More information about the Chocolatey tool.
- link: http://chocolatey.org/
-- name: Chocolatey packages
- description: An overview of the available Chocolatey packages.
- link: http://chocolatey.org/packages
-- ref: become_windows
- description: Some packages, like hotfixes or updates need an interactive user logon
- in order to install. You can use C(become) to achieve this.
-author:
-- Trond Hindenes (@trondhindenes)
-- Peter Mounce (@petemounce)
-- Pepe Barbe (@elventear)
-- Adam Keech (@smadam813)
-- Pierre Templier (@ptemplier)
-- Jordan Borean (@jborean93)
-'''
-
-# TODO:
-# * Better parsing when a package has dependencies - currently fails
-# * Time each item that is run
-# * Support 'changed' with gems - would require shelling out to `gem list` first and parsing, kinda defeating the point of using chocolatey.
-# * Version provided not as string might be translated to 6,6 depending on Locale (results in errors)
-
-EXAMPLES = r'''
-- name: Install git
- win_chocolatey:
- name: git
- state: present
-
-- name: Upgrade installed packages
- win_chocolatey:
- name: all
- state: latest
-
-- name: Install notepadplusplus version 6.6
- win_chocolatey:
- name: notepadplusplus
- version: '6.6'
-
-- name: Install notepadplusplus 32 bit version
- win_chocolatey:
- name: notepadplusplus
- architecture: x86
-
-- name: Install git from specified repository
- win_chocolatey:
- name: git
- source: https://someserver/api/v2/
-
-- name: Install git from a pre configured source (win_chocolatey_source)
- win_chocolatey:
- name: git
- source: internal_repo
-
-- name: Ensure Chocolatey itself is installed and use internal repo as source
- win_chocolatey:
- name: chocolatey
- source: http://someserver/chocolatey
-
-- name: Uninstall git
- win_chocolatey:
- name: git
- state: absent
-
-- name: Install multiple packages
- win_chocolatey:
- name:
- - procexp
- - putty
- - windirstat
- state: present
-
-- name: Install multiple packages sequentially
- win_chocolatey:
- name: '{{ item }}'
- state: present
- loop:
- - procexp
- - putty
- - windirstat
-
-- name: Uninstall multiple packages
- win_chocolatey:
- name:
- - procexp
- - putty
- - windirstat
- state: absent
-
-- name: Install curl using proxy
- win_chocolatey:
- name: curl
- proxy_url: http://proxy-server:8080/
- proxy_username: joe
- proxy_password: p@ssw0rd
-
-- name: Install a package that requires 'become'
- win_chocolatey:
- name: officepro2013
- become: yes
- become_user: Administrator
- become_method: runas
-
-- name: install and pin Notepad++ at 7.6.3
- win_chocolatey:
- name: notepadplusplus
- version: 7.6.3
- pinned: yes
- state: present
-
-- name: remove all pins for Notepad++ on all versions
- win_chocolatey:
- name: notepadplusplus
- pinned: no
- state: present
-'''
-
-RETURN = r'''
-command:
- description: The full command used in the chocolatey task.
- returned: changed
- type: str
- sample: choco.exe install -r --no-progress -y sysinternals --timeout 2700 --failonunfound
-rc:
- description: The return code from the chocolatey task.
- returned: always
- type: int
- sample: 0
-stdout:
- description: The stdout from the chocolatey task. The verbosity level of the
- messages are affected by Ansible verbosity setting, see notes for more
- details.
- returned: changed
- type: str
- sample: Chocolatey upgraded 1/1 packages.
-'''
diff --git a/lib/ansible/modules/windows/win_chocolatey_config.ps1 b/lib/ansible/modules/windows/win_chocolatey_config.ps1
deleted file mode 100644
index 119b12648d..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey_config.ps1
+++ /dev/null
@@ -1,122 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.ArgvParser
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff = Get-AnsibleParam -obj $params -name "_ansible_diff" -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 "absent", "present"
-$value = Get-AnsibleParam -obj $params -name "value" -type "str" -failifempty ($state -eq "present")
-
-$result = @{
- changed = $false
-}
-if ($diff) {
- $result.diff = @{
- before = $null
- after = $null
- }
-}
-
-if ($state -eq "present") {
- if ($value -eq "") {
- Fail-Json -obj $result -message "Cannot set Chocolatey config as an empty string when state=present, use state=absent instead"
- }
- # make sure bool values are lower case
- if ($value -ceq "True" -or $value -ceq "False") {
- $value = $value.ToLower()
- }
-}
-
-Function Get-ChocolateyConfig {
- param($choco_app)
-
- # 'choco config list -r' does not display an easily parsable config entries
- # It contains config/sources/feature in the one command, and is in the
- # structure 'configKey = configValue | description', if the key or value
- # contains a = or |, it will make it quite hard to easily parse it,
- # compared to reading an XML file that already delimits these values
- $choco_config_path = "$(Split-Path -Path (Split-Path -Path $choco_app.Path))\config\chocolatey.config"
- if (-not (Test-Path -Path $choco_config_path)) {
- Fail-Json -obj $result -message "Expecting Chocolatey config file to exist at '$choco_config_path'"
- }
-
- try {
- [xml]$choco_config = Get-Content -Path $choco_config_path
- } catch {
- Fail-Json -obj $result -message "Failed to parse Chocolatey config file at '$choco_config_path': $($_.Exception.Message)"
- }
-
- $config_info = @{}
- foreach ($config in $choco_config.chocolatey.config.GetEnumerator()) {
- $config_info."$($config.key)" = $config.value
- }
-
- return ,$config_info
-}
-
-Function Remove-ChocolateyConfig {
- param(
- $choco_app,
- $name
- )
- $command = Argv-ToString -arguments @($choco_app.Path, "config", "unset", "--name", $name)
- $res = Run-Command -command $command
- if ($res.rc -ne 0) {
- Fail-Json -obj $result -message "Failed to unset Chocolatey config for '$name': $($res.stderr)"
- }
-}
-
-Function Set-ChocolateyConfig {
- param(
- $choco_app,
- $name,
- $value
- )
- $command = Argv-ToString -arguments @($choco_app.Path, "config", "set", "--name", $name, "--value", $value)
- $res = Run-Command -command $command
- if ($res.rc -ne 0) {
- Fail-Json -obj $result -message "Failed to set Chocolatey config for '$name' to '$value': $($res.stderr)"
- }
-}
-
-$choco_app = Get-Command -Name choco.exe -CommandType Application -ErrorAction SilentlyContinue
-if (-not $choco_app) {
- Fail-Json -obj $result -message "Failed to find Chocolatey installation, make sure choco.exe is in the PATH env value"
-}
-
-$config_info = Get-ChocolateyConfig -choco_app $choco_app
-if ($name -notin $config_info.Keys) {
- Fail-Json -obj $result -message "The Chocolatey config '$name' is not an existing config value, check the spelling. Valid config names: $($config_info.Keys -join ', ')"
-}
-if ($diff) {
- $result.diff.before = $config_info.$name
-}
-
-if ($state -eq "absent" -and $config_info.$name -ne "") {
- if (-not $check_mode) {
- Remove-ChocolateyConfig -choco_app $choco_app -name $name
- }
- $result.changed = $true
-# choco.exe config set is not case sensitive, it won't make a change if the
-# value is the same but doesn't match
-} elseif ($state -eq "present" -and $config_info.$name -ne $value) {
- if (-not $check_mode) {
- Set-ChocolateyConfig -choco_app $choco_app -name $name -value $value
- }
- $result.changed = $true
- if ($diff) {
- $result.diff.after = $value
- }
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_chocolatey_config.py b/lib/ansible/modules/windows/win_chocolatey_config.py
deleted file mode 100644
index 1d20bab311..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey_config.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_chocolatey_config
-version_added: '2.7'
-short_description: Manages Chocolatey config settings
-description:
-- Used to manage Chocolatey config settings as well as unset the values.
-options:
- name:
- description:
- - The name of the config setting to manage.
- - See U(https://chocolatey.org/docs/chocolatey-configuration) for a list of
- valid configuration settings that can be changed.
- - Any config values that contain encrypted values like a password are not
- idempotent as the plaintext value cannot be read.
- type: str
- required: yes
- state:
- description:
- - When C(absent), it will ensure the setting is unset or blank.
- - When C(present), it will ensure the setting is set to the value of
- I(value).
- type: str
- choices: [ absent, present ]
- default: present
- value:
- description:
- - Used when C(state=present) that contains the value to set for the config
- setting.
- - Cannot be null or an empty string, use C(state=absent) to unset a config
- value instead.
- type: str
-seealso:
-- module: win_chocolatey
-- module: win_chocolatey_facts
-- module: win_chocolatey_feature
-- module: win_chocolatey_source
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Set the cache location
- win_chocolatey_config:
- name: cacheLocation
- state: present
- value: D:\chocolatey_temp
-
-- name: Unset the cache location
- win_chocolatey_config:
- name: cacheLocation
- state: absent
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_chocolatey_facts.ps1 b/lib/ansible/modules/windows/win_chocolatey_facts.ps1
deleted file mode 100644
index fdbdc96725..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey_facts.ps1
+++ /dev/null
@@ -1,182 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Ansible Project
-# Copyright: (c) 2018, Simon Baerlocher <s.baerlocher@sbaerlocher.ch>
-# Copyright: (c) 2018, ITIGO AG <opensource@itigo.ch>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.ArgvParser
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-Set-StrictMode -Version 2.0
-
-# Create a new result object
-$result = @{
- changed = $false
- ansible_facts = @{
- ansible_chocolatey = @{
- config = @{}
- feature = @{}
- sources = @()
- packages = @()
- }
- }
-}
-
-$choco_app = Get-Command -Name choco.exe -CommandType Application -ErrorAction SilentlyContinue
-if (-not $choco_app) {
- Fail-Json -obj $result -message "Failed to find Chocolatey installation, make sure choco.exe is in the PATH env value"
-}
-
-Function Get-ChocolateyFeature {
-
- param($choco_app)
-
- $command = Argv-ToString -arguments $choco_app.Path, "feature", "list", "-r"
- $res = Run-Command -command $command
- if ($res.rc -ne 0) {
- $result.stdout = $res.stdout
- $result.stderr = $res.stderr
- $result.rc = $res.rc
- Fail-Json -obj $result -message "Failed to list Chocolatey features, see stderr"
- }
-
- $feature_info = @{}
- $res.stdout -split "`r`n" | Where-Object { $_ -ne "" } | ForEach-Object {
- $feature_split = $_ -split "\|"
- $feature_info."$($feature_split[0])" = $feature_split[1] -eq "Enabled"
- }
- $result.ansible_facts.ansible_chocolatey.feature = $feature_info
-}
-
-Function Get-ChocolateyConfig {
-
- param($choco_app)
-
- $choco_config_path = "$(Split-Path -Path (Split-Path -Path $choco_app.Path))\config\chocolatey.config"
- if (-not (Test-Path -Path $choco_config_path)) {
- Fail-Json -obj $result -message "Expecting Chocolatey config file to exist at '$choco_config_path'"
- }
-
- try {
- [xml]$choco_config = Get-Content -Path $choco_config_path
- } catch {
- Fail-Json -obj $result -message "Failed to parse Chocolatey config file at '$choco_config_path': $($_.Exception.Message)"
- }
-
- $config_info = @{}
- foreach ($config in $choco_config.chocolatey.config.GetEnumerator()) {
- # try and parse as a boot, then an int, fallback to string
- try {
- $value = [System.Boolean]::Parse($config.value)
- } catch {
- try {
- $value = [System.Int32]::Parse($config.value)
- } catch {
- $value = $config.value
- }
- }
- $config_info."$($config.key)" = $value
- }
- $result.ansible_facts.ansible_chocolatey.config = $config_info
-}
-
-Function Get-ChocolateyPackages {
-
- param($choco_app)
-
- $command = Argv-ToString -arguments $choco_app.Path, "list", "--local-only", "--limit-output", "--all-versions"
- $res = Run-Command -command $command
- if ($res.rc -ne 0) {
- $result.stdout = $res.stdout
- $result.stderr = $res.stderr
- $result.rc = $res.rc
- Fail-Json -obj $result -message "Failed to list Chocolatey Packages, see stderr"
- }
-
- $packages_info = [System.Collections.ArrayList]@()
- $res.stdout.Split("`r`n", [System.StringSplitOptions]::RemoveEmptyEntries) | ForEach-Object {
- $packages_split = $_ -split "\|"
- $package_info = @{
- package = $packages_split[0]
- version = $packages_split[1]
- }
- $packages_info.Add($package_info) > $null
- }
- $result.ansible_facts.ansible_chocolatey.packages = $packages_info
-}
-
-Function Get-ChocolateySources {
- param($choco_app)
-
- $choco_config_path = "$(Split-Path -Path (Split-Path -Path $choco_app.Path))\config\chocolatey.config"
- if (-not (Test-Path -LiteralPath $choco_config_path)) {
- Fail-Json -obj $result -message "Expecting Chocolatey config file to exist at '$choco_config_path'"
- }
-
- try {
- [xml]$choco_config = Get-Content -Path $choco_config_path
- } catch {
- Fail-Json -obj $result -message "Failed to parse Chocolatey config file at '$choco_config_path': $($_.Exception.Message)"
- }
-
- $sources = [System.Collections.ArrayList]@()
- foreach ($xml_source in $choco_config.chocolatey.sources.GetEnumerator()) {
- $source_username = $xml_source.Attributes.GetNamedItem("user")
- if ($null -ne $source_username) {
- $source_username = $source_username.Value
- }
-
- # 0.9.9.9+
- $priority = $xml_source.Attributes.GetNamedItem("priority")
- if ($null -ne $priority) {
- $priority = [int]$priority.Value
- }
-
- # 0.9.10+
- $certificate = $xml_source.Attributes.GetNamedItem("certificate")
- if ($null -ne $certificate) {
- $certificate = $certificate.Value
- }
-
- # 0.10.4+
- $bypass_proxy = $xml_source.Attributes.GetNamedItem("bypassProxy")
- if ($null -ne $bypass_proxy) {
- $bypass_proxy = [System.Convert]::ToBoolean($bypass_proxy.Value)
- }
- $allow_self_service = $xml_source.Attributes.GetNamedItem("selfService")
- if ($null -ne $allow_self_service) {
- $allow_self_service = [System.Convert]::ToBoolean($allow_self_service.Value)
- }
-
- # 0.10.8+
- $admin_only = $xml_source.Attributes.GetNamedItem("adminOnly")
- if ($null -ne $admin_only) {
- $admin_only = [System.Convert]::ToBoolean($admin_only.Value)
- }
-
- $source_info = @{
- name = $xml_source.id
- source = $xml_source.value
- disabled = [System.Convert]::ToBoolean($xml_source.disabled)
- source_username = $source_username
- priority = $priority
- certificate = $certificate
- bypass_proxy = $bypass_proxy
- allow_self_service = $allow_self_service
- admin_only = $admin_only
- }
- $sources.Add($source_info) > $null
- }
- $result.ansible_facts.ansible_chocolatey.sources = $sources
-}
-
-Get-ChocolateyConfig -choco_app $choco_app
-Get-ChocolateyFeature -choco_app $choco_app
-Get-ChocolateyPackages -choco_app $choco_app
-Get-ChocolateySources -choco_app $choco_app
-
-# Return result
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_chocolatey_facts.py b/lib/ansible/modules/windows/win_chocolatey_facts.py
deleted file mode 100644
index d35f14d012..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey_facts.py
+++ /dev/null
@@ -1,144 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ansible Project
-# Copyright: (c) 2018, Simon Baerlocher <s.baerlocher@sbaerlocher.ch>
-# Copyright: (c) 2018, ITIGO AG <opensource@itigo.ch>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_chocolatey_facts
-version_added: '2.8'
-short_description: Create a facts collection for Chocolatey
-description:
-- This module shows information from Chocolatey, such as installed packages, configuration, feature and sources.
-notes:
-- Chocolatey must be installed beforehand, use M(win_chocolatey) to do this.
-seealso:
-- module: win_chocolatey
-- module: win_chocolatey_config
-- module: win_chocolatey_feature
-- module: win_chocolatey_source
-author:
-- Simon Bärlocher (@sbaerlocher)
-- ITIGO AG (@itigoag)
-'''
-
-EXAMPLES = r'''
-- name: Gather facts from chocolatey
- win_chocolatey_facts:
-
-- name: Displays the Configuration
- debug:
- var: ansible_chocolatey.config
-
-- name: Displays the Feature
- debug:
- var: ansible_chocolatey.feature
-
-- name: Displays the Sources
- debug:
- var: ansible_chocolatey.sources
-
-- name: Displays the Packages
- debug:
- var: ansible_chocolatey.packages
-'''
-
-RETURN = r'''
-ansible_facts:
- description: Detailed information about the Chocolatey installation
- returned: always
- type: complex
- contains:
- ansible_chocolatey:
- description: Detailed information about the Chocolatey installation
- returned: always
- type: complex
- contains:
- config:
- description: Detailed information about stored the configurations
- returned: always
- type: dict
- sample:
- commandExecutionTimeoutSeconds: 2700
- containsLegacyPackageInstalls: true
- feature:
- description: Detailed information about enabled and disabled features
- returned: always
- type: dict
- sample:
- allowEmptyCheckums: false
- autoUninstaller: true
- failOnAutoUninstaller: false
- sources:
- description: List of Chocolatey sources
- returned: always
- type: complex
- contains:
- admin_only:
- description: Is the source visible to Administrators only
- returned: always
- type: bool
- sample: false
- allow_self_service:
- description: Is the source allowed to be used with self-service
- returned: always
- type: bool
- sample: false
- bypass_proxy:
- description: Can the source explicitly bypass configured proxies
- returned: always
- type: bool
- sample: true
- certificate:
- description: Path to a PFX certificate for X509 authenticated feeds
- returned: always
- type: str
- sample: C:\chocolatey\cert.pfx
- disabled:
- description: Is the source disabled
- returned: always
- type: bool
- sample: false
- name:
- description: Name of the source
- returned: always
- type: str
- sample: chocolatey
- priority:
- description: The priority order of this source, lower is better, 0 is no priority
- returned: always
- type: int
- sample: 0
- source:
- description: The source, can be a folder/file or an url
- returned: always
- type: str
- sample: https://chocolatey.org/api/v2/
- source_username:
- description: Username used to access authenticated feeds
- returned: always
- type: str
- sample: username
- packages:
- description: List of installed Packages
- returned: always
- type: complex
- contains:
- package:
- description: Name of the package
- returned: always
- type: str
- sample: vscode
- version:
- description: Version of the package
- returned: always
- type: str
- sample: '1.27.2'
-'''
diff --git a/lib/ansible/modules/windows/win_chocolatey_feature.ps1 b/lib/ansible/modules/windows/win_chocolatey_feature.ps1
deleted file mode 100644
index a33378cd6a..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey_feature.ps1
+++ /dev/null
@@ -1,74 +0,0 @@
-#!powershell
-
-# Copyright: (c), 2018 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-$params = Parse-Args -arguments $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 "enabled" -validateset "disabled", "enabled"
-
-$result = @{
- changed = $false
-}
-
-Function Get-ChocolateyFeatures {
- param($choco_app)
-
- $res = Run-Command -command "`"$($choco_app.Path)`" feature list -r"
- if ($res.rc -ne 0) {
- Fail-Json -obj $result -message "Failed to list Chocolatey features: $($res.stderr)"
- }
- $feature_info = @{}
- $res.stdout -split "`r`n" | Where-Object { $_ -ne "" } | ForEach-Object {
- $feature_split = $_ -split "\|"
- $feature_info."$($feature_split[0])" = $feature_split[1] -eq "Enabled"
- }
-
- return ,$feature_info
-}
-
-Function Set-ChocolateyFeature {
- param(
- $choco_app,
- $name,
- $enabled
- )
-
- if ($enabled) {
- $state_string = "enable"
- } else {
- $state_string = "disable"
- }
- $res = Run-Command -command "`"$($choco_app.Path)`" feature $state_string --name `"$name`""
- if ($res.rc -ne 0) {
- Fail-Json -obj $result -message "Failed to set Chocolatey feature $name to $($state_string): $($res.stderr)"
- }
-}
-
-$choco_app = Get-Command -Name choco.exe -CommandType Application -ErrorAction SilentlyContinue
-if (-not $choco_app) {
- Fail-Json -obj $result -message "Failed to find Chocolatey installation, make sure choco.exe is in the PATH env value"
-}
-
-$feature_info = Get-ChocolateyFeatures -choco_app $choco_app
-if ($name -notin $feature_info.keys) {
- Fail-Json -obj $result -message "Invalid feature name '$name' specified, valid features are: $($feature_info.keys -join ', ')"
-}
-
-$expected_status = $state -eq "enabled"
-$feature_status = $feature_info.$name
-if ($feature_status -ne $expected_status) {
- if (-not $check_mode) {
- Set-ChocolateyFeature -choco_app $choco_app -name $name -enabled $expected_status
- }
- $result.changed = $true
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_chocolatey_feature.py b/lib/ansible/modules/windows/win_chocolatey_feature.py
deleted file mode 100644
index 13358f4e1e..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey_feature.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_chocolatey_feature
-version_added: '2.7'
-short_description: Manages Chocolatey features
-description:
-- Used to enable or disable features in Chocolatey.
-options:
- name:
- description:
- - The name of the feature to manage.
- - Run C(choco.exe feature list) to get a list of features that can be
- managed.
- type: str
- required: yes
- state:
- description:
- - When C(disabled) then the feature will be disabled.
- - When C(enabled) then the feature will be enabled.
- type: str
- choices: [ disabled, enabled ]
- default: enabled
-seealso:
-- module: win_chocolatey
-- module: win_chocolatey_config
-- module: win_chocolatey_facts
-- module: win_chocolatey_source
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Disable file checksum matching
- win_chocolatey_feature:
- name: checksumFiles
- state: disabled
-
-- name: Stop Chocolatey on the first package failure
- win_chocolatey_feature:
- name: stopOnFirstPackageFailure
- state: enabled
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_chocolatey_source.ps1 b/lib/ansible/modules/windows/win_chocolatey_source.ps1
deleted file mode 100644
index c2360f153a..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey_source.ps1
+++ /dev/null
@@ -1,306 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.ArgvParser
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff = Get-AnsibleParam -obj $params -name "_ansible_diff" -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 "absent", "disabled", "present"
-
-$admin_only = Get-AnsibleParam -obj $params -name "admin_only" -type "bool"
-$allow_self_service = Get-AnsibleParam -obj $params -name "allow_self_service" -type "bool"
-$bypass_proxy = Get-AnsibleParam -obj $params -name "bypass_proxy" -type "bool"
-$certificate = Get-AnsibleParam -obj $params -name "certificate" -type "str"
-$certificate_password = Get-AnsibleParam -obj $params -name "certificate_password" -type "str"
-$priority = Get-AnsibleParam -obj $params -name "priority" -type "int"
-$source = Get-AnsibleParam -obj $params -name "source" -type "str"
-$source_username = Get-AnsibleParam -obj $params -name "source_username" -type "str"
-$source_password = Get-AnsibleParam -obj $params -name "source_password" -type "str" -failifempty ($null -ne $source_username)
-$update_password = Get-AnsibleParam -obj $params -name "update_password" -type "str" -default "always" -validateset "always", "on_create"
-
-$result = @{
- changed = $false
-}
-if ($diff) {
- $result.diff = @{
- before = @{}
- after = @{}
- }
-}
-
-Function Get-ChocolateySources {
- param($choco_app)
-
- $choco_config_path = "$(Split-Path -Path (Split-Path -Path $choco_app.Path))\config\chocolatey.config"
- if (-not (Test-Path -LiteralPath $choco_config_path)) {
- Fail-Json -obj $result -message "Expecting Chocolatey config file to exist at '$choco_config_path'"
- }
-
- # would prefer to enumerate the existing sources with an actual API but the
- # only stable interface is choco.exe source list and that does not output
- # the sources in an easily parsable list. Using -r will split each entry by
- # | like a psv but does not quote values that have a | already in it making
- # it inadequete for our tasks. Instead we will parse the chocolatey.config
- # file and get the values from there
- try {
- [xml]$choco_config = Get-Content -Path $choco_config_path
- } catch {
- Fail-Json -obj $result -message "Failed to parse Chocolatey config file at '$choco_config_path': $($_.Exception.Message)"
- }
-
- $sources = [System.Collections.ArrayList]@()
- foreach ($xml_source in $choco_config.chocolatey.sources.GetEnumerator()) {
- $source_username = $xml_source.Attributes.GetNamedItem("user")
- if ($null -ne $source_username) {
- $source_username = $source_username.Value
- }
-
- # 0.9.9.9+
- $priority = $xml_source.Attributes.GetNamedItem("priority")
- if ($null -ne $priority) {
- $priority = [int]$priority.Value
- }
-
- # 0.9.10+
- $certificate = $xml_source.Attributes.GetNamedItem("certificate")
- if ($null -ne $certificate) {
- $certificate = $certificate.Value
- }
-
- # 0.10.4+
- $bypass_proxy = $xml_source.Attributes.GetNamedItem("bypassProxy")
- if ($null -ne $bypass_proxy) {
- $bypass_proxy = [System.Convert]::ToBoolean($bypass_proxy.Value)
- }
- $allow_self_service = $xml_source.Attributes.GetNamedItem("selfService")
- if ($null -ne $allow_self_service) {
- $allow_self_service = [System.Convert]::ToBoolean($allow_self_service.Value)
- }
-
- # 0.10.8+
- $admin_only = $xml_source.Attributes.GetNamedItem("adminOnly")
- if ($null -ne $admin_only) {
- $admin_only = [System.Convert]::ToBoolean($admin_only.Value)
- }
-
- $source_info = @{
- name = $xml_source.id
- source = $xml_source.value
- disabled = [System.Convert]::ToBoolean($xml_source.disabled)
- source_username = $source_username
- priority = $priority
- certificate = $certificate
- bypass_proxy = $bypass_proxy
- allow_self_service = $allow_self_service
- admin_only = $admin_only
- }
- $sources.Add($source_info) > $null
- }
- return ,$sources
-}
-
-Function New-ChocolateySource {
- param(
- $choco_app,
- $name,
- $source,
- $source_username,
- $source_password,
- $certificate,
- $certificate_password,
- $priority,
- $bypass_proxy,
- $allow_self_service,
- $admin_only
- )
- # build the base arguments
- $arguments = [System.Collections.ArrayList]@($choco_app.Path,
- "source", "add", "--name", $name, "--source", $source
- )
-
- # add optional arguments from user input
- if ($null -ne $source_username) {
- $arguments.Add("--user") > $null
- $arguments.Add($source_username) > $null
- $arguments.Add("--password") > $null
- $arguments.Add($source_password) > $null
- }
- if ($null -ne $certificate) {
- $arguments.Add("--cert") > $null
- $arguments.Add($certificate) > $null
- }
- if ($null -ne $certificate_password) {
- $arguments.Add("--certpassword") > $null
- $arguments.Add($certificate_password) > $null
- }
- if ($null -ne $priority) {
- $arguments.Add("--priority") > $null
- $arguments.Add($priority) > $null
- } else {
- $priority = 0
- }
- if ($bypass_proxy -eq $true) {
- $arguments.Add("--bypass-proxy") > $null
- } else {
- $bypass_proxy = $false
- }
- if ($allow_self_service -eq $true) {
- $arguments.Add("--allow-self-service") > $null
- } else {
- $allow_self_service = $false
- }
- if ($admin_only -eq $true) {
- $arguments.Add("--admin-only") > $null
- } else {
- $admin_only = $false
- }
-
- if ($check_mode) {
- $arguments.Add("--what-if") > $null
- }
-
- $command = Argv-ToString -arguments $arguments
- $res = Run-Command -command $command
- if ($res.rc -ne 0) {
- Fail-Json -obj $result -message "Failed to add Chocolatey source '$name': $($res.stderr)"
- }
-
- $source_info = @{
- name = $name
- source = $source
- disabled = $false
- source_username = $source_username
- priority = $priority
- certificate = $certificate
- bypass_proxy = $bypass_proxy
- allow_self_service = $allow_self_service
- admin_only = $admin_only
- }
- return ,$source_info
-}
-
-Function Remove-ChocolateySource {
- param(
- $choco_app,
- $name
- )
- $arguments = [System.Collections.ArrayList]@($choco_app.Path, "source", "remove", "--name", $name)
- if ($check_mode) {
- $arguments.Add("--what-if") > $null
- }
- $command = Argv-ToString -arguments $arguments
- $res = Run-Command -command $command
- if ($res.rc -ne 0) {
- Fail-Json -obj $result -message "Failed to remove Chocolatey source '$name': $($_.res.stderr)"
- }
-}
-
-$choco_app = Get-Command -Name choco.exe -CommandType Application -ErrorAction SilentlyContinue
-if (-not $choco_app) {
- Fail-Json -obj $result -message "Failed to find Chocolatey installation, make sure choco.exe is in the PATH env value"
-}
-$actual_sources = Get-ChocolateySources -choco_app $choco_app
-$actual_source = $actual_sources | Where-Object { $_.name -eq $name }
-if ($diff) {
- if ($null -ne $actual_source) {
- $before = $actual_source.Clone()
- } else {
- $before = @{}
- }
- $result.diff.before = $before
-}
-
-if ($state -eq "absent" -and $null -ne $actual_source) {
- Remove-ChocolateySource -choco_app $choco_app -name $name
- $result.changed = $true
-} elseif ($state -in ("disabled", "present")) {
- $change = $false
- if ($null -eq $actual_source) {
- if ($null -eq $source) {
- Fail-Json -obj $result -message "The source option must be set when creating a new source"
- }
- $change = $true
- } else {
- if ($null -ne $source -and $source -ne $actual_source.source) {
- $change = $true
- }
- if ($null -ne $source_username -and $source_username -ne $actual_source.source_username) {
- $change = $true
- }
- if ($null -ne $source_password -and $update_password -eq "always") {
- $change = $true
- }
- if ($null -ne $certificate -and $certificate -ne $actual_source.certificate) {
- $change = $true
- }
- if ($null -ne $certificate_password -and $update_password -eq "always") {
- $change = $true
- }
- if ($null -ne $priority -and $priority -ne $actual_source.priority) {
- $change = $true
- }
- if ($null -ne $bypass_proxy -and $bypass_proxy -ne $actual_source.bypass_proxy) {
- $change = $true
- }
- if ($null -ne $allow_self_service -and $allow_self_service -ne $actual_source.allow_self_service) {
- $change = $true
- }
- if ($null -ne $admin_only -and $admin_only -ne $actual_source.admin_only) {
- $change = $true
- }
-
- if ($change) {
- Remove-ChocolateySource -choco_app $choco_app -name $name
- $result.changed = $true
- }
- }
-
- if ($change) {
- $actual_source = New-ChocolateySource -choco_app $choco_app -name $name -source $source `
- -source_username $source_username -source_password $source_password `
- -certificate $certificate -certificate_password $certificate_password `
- -priority $priority -bypass_proxy $bypass_proxy -allow_self_service $allow_self_service `
- -admin_only $admin_only
- $result.changed = $true
- }
-
- # enable/disable the source if necessary
- $status_action = $null
- if ($state -ne "disabled" -and $actual_source.disabled) {
- $status_action = "enable"
- } elseif ($state -eq "disabled" -and (-not $actual_source.disabled)) {
- $status_action = "disable"
- }
- if ($null -ne $status_action) {
- $arguments = [System.Collections.ArrayList]@($choco_app.Path, "source", $status_action, "--name", $name)
- if ($check_mode) {
- $arguments.Add("--what-if") > $null
- }
- $command = Argv-ToString -arguments $arguments
- $res = Run-Command -command $command
- if ($res.rc -ne 0) {
- Fail-Json -obj $result -message "Failed to $status_action Chocolatey source '$name': $($res.stderr)"
- }
- $actual_source.disabled = ($status_action -eq "disable")
- $result.changed = $true
- }
-
- if ($diff) {
- $after = $actual_source
- $result.diff.after = $after
- }
-}
-
-# finally remove the diff if there was no change
-if (-not $result.changed -and $diff) {
- $result.diff = @{}
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_chocolatey_source.py b/lib/ansible/modules/windows/win_chocolatey_source.py
deleted file mode 100644
index 0e1fc0f588..0000000000
--- a/lib/ansible/modules/windows/win_chocolatey_source.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_chocolatey_source
-version_added: '2.7'
-short_description: Manages Chocolatey sources
-description:
-- Used to managed Chocolatey sources configured on the client.
-- Requires Chocolatey to be already installed on the remote host.
-options:
- admin_only:
- description:
- - Makes the source visible to Administrators only.
- - Requires Chocolatey >= 0.10.8.
- - When creating a new source, this defaults to C(no).
- type: bool
- allow_self_service:
- description:
- - Allow the source to be used with self-service
- - Requires Chocolatey >= 0.10.4.
- - When creating a new source, this defaults to C(no).
- type: bool
- bypass_proxy:
- description:
- - Bypass the proxy when using this source.
- - Requires Chocolatey >= 0.10.4.
- - When creating a new source, this defaults to C(no).
- type: bool
- certificate:
- description:
- - The path to a .pfx file to use for X509 authenticated feeds.
- - Requires Chocolatey >= 0.9.10.
- type: str
- certificate_password:
- description:
- - The password for I(certificate) if required.
- - Requires Chocolatey >= 0.9.10.
- name:
- description:
- - The name of the source to configure.
- required: yes
- priority:
- description:
- - The priority order of this source compared to other sources, lower is
- better.
- - All priorities above C(0) will be evaluated first, then zero-based values
- will be evaluated in config file order.
- - Requires Chocolatey >= 0.9.9.9.
- - When creating a new source, this defaults to C(0).
- type: int
- source:
- description:
- - The file/folder/url of the source.
- - Required when I(state) is C(present) or C(disabled) and the source does
- not already exist.
- source_username:
- description:
- - The username used to access I(source).
- source_password:
- description:
- - The password for I(source_username).
- - Required if I(source_username) is set.
- state:
- description:
- - When C(absent), will remove the source.
- - When C(disabled), will ensure the source exists but is disabled.
- - When C(present), will ensure the source exists and is enabled.
- choices:
- - absent
- - disabled
- - present
- default: present
- update_password:
- description:
- - When C(always), the module will always set the password and report a
- change if I(certificate_password) or I(source_password) is set.
- - When C(on_create), the module will only set the password if the source
- is being created.
- choices:
- - always
- - on_create
- default: always
-seealso:
-- module: win_chocolatey
-- module: win_chocolatey_config
-- module: win_chocolatey_facts
-- module: win_chocolatey_feature
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Remove the default public source
- win_chocolatey_source:
- name: chocolatey
- state: absent
-
-- name: Add new internal source
- win_chocolatey_source:
- name: internal repo
- state: present
- source: http://chocolatey-server/chocolatey
-
-- name: Create HTTP source with credentials
- win_chocolatey_source:
- name: internal repo
- state: present
- source: https://chocolatey-server/chocolatey
- source_username: username
- source_password: password
-
-- name: Disable Chocolatey source
- win_chocolatey_source:
- name: chocolatey
- state: disabled
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_computer_description.ps1 b/lib/ansible/modules/windows/win_computer_description.ps1
deleted file mode 100644
index f1b75d1ab0..0000000000
--- a/lib/ansible/modules/windows/win_computer_description.ps1
+++ /dev/null
@@ -1,54 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, RusoSova
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#AnsibleRequires -OSVersion 6.1
-
-$spec = @{
- options = @{
- owner = @{ type="str" }
- organization = @{ type="str" }
- description = @{ type="str" }
- }
- required_one_of = @(
- ,@('owner', 'organization', 'description')
- )
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$owner = $module.Params.owner
-$organization = $module.Params.organization
-$description = $module.Params.description
-$regPath="HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\"
-
-#Change description
-if ($description -or $description -eq "") {
- $descriptionObject=Get-CimInstance -class "Win32_OperatingSystem"
- if ($description -cne $descriptionObject.description) {
- Set-CimInstance -InputObject $descriptionObject -Property @{"Description"="$description"} -WhatIf:$module.CheckMode
- $module.Result.changed = $true
- }
-}
-
-#Change owner
-if ($owner -or $owner -eq "") {
- $curentOwner=(Get-ItemProperty -LiteralPath $regPath -Name RegisteredOwner).RegisteredOwner
- if ($curentOwner -cne $owner) {
- Set-ItemProperty -LiteralPath $regPath -Name "RegisteredOwner" -Value $owner -WhatIf:$module.CheckMode
- $module.Result.changed = $true
- }
-}
-
-#Change organization
-if ($organization -or $organization -eq "") {
- $curentOrganization=(Get-ItemProperty -LiteralPath $regPath -Name RegisteredOrganization).RegisteredOrganization
- if ($curentOrganization -cne $organization) {
- Set-ItemProperty -LiteralPath $regPath -Name "RegisteredOrganization" -Value $organization -WhatIf:$module.CheckMode
- $module.Result.changed = $true
- }
-}
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_computer_description.py b/lib/ansible/modules/windows/win_computer_description.py
deleted file mode 100644
index b8aa276185..0000000000
--- a/lib/ansible/modules/windows/win_computer_description.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2019, RusoSova
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = r'''
----
-module: win_computer_description
-short_description: Set windows description, owner and organization
-description:
- - This module sets Windows description that is shown under My Computer properties. Module also sets
- Windows license owner and organization. License information can be viewed by running winver commad.
-options:
- description:
- description:
- - String value to apply to Windows descripton. Specify value of "" to clear the value.
- required: false
- type: str
- organization:
- description:
- - String value of organization that the Windows is licensed to. Specify value of "" to clear the value.
- required: false
- type: str
- owner:
- description:
- - String value of the persona that the Windows is licensed to. Specify value of "" to clear the value.
- required: false
- type: str
-version_added: '2.10'
-author:
- - RusoSova (@RusoSova)
-'''
-
-EXAMPLES = r'''
-- name: Set Windows description, owner and organization
- win_computer_description:
- description: Best Box
- owner: RusoSova
- organization: MyOrg
- register: result
-
-- name: Set Windows description only
- win_computer_description:
- description: This is my Windows machine
- register: result
-
-- name: Set organization and clear owner field
- win_computer_description:
- owner: ''
- organization: Black Mesa
-
-- name: Clear organization, description and owner
- win_computer_description:
- organization: ""
- owner: ""
- description: ""
- register: result
-'''
-
-RETURN = r'''
-#
-'''
diff --git a/lib/ansible/modules/windows/win_credential.ps1 b/lib/ansible/modules/windows/win_credential.ps1
deleted file mode 100644
index fdc83584f0..0000000000
--- a/lib/ansible/modules/windows/win_credential.ps1
+++ /dev/null
@@ -1,714 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.AddType
-
-$spec = @{
- options = @{
- alias = @{ type = "str" }
- attributes = @{
- type = "list"
- elements = "dict"
- options = @{
- name = @{ type = "str"; required = $true }
- data = @{ type = "str" }
- data_format = @{ type = "str"; default = "text"; choices = @("base64", "text") }
- }
- }
- comment = @{ type = "str" }
- name = @{ type = "str"; required = $true }
- persistence = @{ type = "str"; default = "local"; choices = @("enterprise", "local") }
- secret = @{ type = "str"; no_log = $true }
- secret_format = @{ type = "str"; default = "text"; choices = @("base64", "text") }
- state = @{ type = "str"; default = "present"; choices = @("absent", "present") }
- type = @{
- type = "str"
- required = $true
- choices = @("domain_password", "domain_certificate", "generic_password", "generic_certificate")
- }
- update_secret = @{ type = "str"; default = "always"; choices = @("always", "on_create") }
- username = @{ type = "str" }
- }
- required_if = @(
- ,@("state", "present", @("username"))
- )
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$alias = $module.Params.alias
-$attributes = $module.Params.attributes
-$comment = $module.Params.comment
-$name = $module.Params.name
-$persistence = $module.Params.persistence
-$secret = $module.Params.secret
-$secret_format = $module.Params.secret_format
-$state = $module.Params.state
-$type = $module.Params.type
-$update_secret = $module.Params.update_secret
-$username = $module.Params.username
-
-$module.Diff.before = ""
-$module.Diff.after = ""
-
-Add-CSharpType -AnsibleModule $module -References @'
-using Microsoft.Win32.SafeHandles;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.ConstrainedExecution;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace Ansible.CredentialManager
-{
- internal class NativeHelpers
- {
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public class CREDENTIAL
- {
- public CredentialFlags Flags;
- public CredentialType Type;
- [MarshalAs(UnmanagedType.LPWStr)] public string TargetName;
- [MarshalAs(UnmanagedType.LPWStr)] public string Comment;
- public FILETIME LastWritten;
- public UInt32 CredentialBlobSize;
- public IntPtr CredentialBlob;
- public CredentialPersist Persist;
- public UInt32 AttributeCount;
- public IntPtr Attributes;
- [MarshalAs(UnmanagedType.LPWStr)] public string TargetAlias;
- [MarshalAs(UnmanagedType.LPWStr)] public string UserName;
-
- public static explicit operator Credential(CREDENTIAL v)
- {
- byte[] secret = new byte[(int)v.CredentialBlobSize];
- if (v.CredentialBlob != IntPtr.Zero)
- Marshal.Copy(v.CredentialBlob, secret, 0, secret.Length);
-
- List<CredentialAttribute> attributes = new List<CredentialAttribute>();
- if (v.AttributeCount > 0)
- {
- CREDENTIAL_ATTRIBUTE[] rawAttributes = new CREDENTIAL_ATTRIBUTE[v.AttributeCount];
- Credential.PtrToStructureArray(rawAttributes, v.Attributes);
- attributes = rawAttributes.Select(x => (CredentialAttribute)x).ToList();
- }
-
- string userName = v.UserName;
- if (v.Type == CredentialType.DomainCertificate || v.Type == CredentialType.GenericCertificate)
- userName = Credential.UnmarshalCertificateCredential(userName);
-
- return new Credential
- {
- Type = v.Type,
- TargetName = v.TargetName,
- Comment = v.Comment,
- LastWritten = (DateTimeOffset)v.LastWritten,
- Secret = secret,
- Persist = v.Persist,
- Attributes = attributes,
- TargetAlias = v.TargetAlias,
- UserName = userName,
- Loaded = true,
- };
- }
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct CREDENTIAL_ATTRIBUTE
- {
- [MarshalAs(UnmanagedType.LPWStr)] public string Keyword;
- public UInt32 Flags; // Set to 0 and is reserved
- public UInt32 ValueSize;
- public IntPtr Value;
-
- public static explicit operator CredentialAttribute(CREDENTIAL_ATTRIBUTE v)
- {
- byte[] value = new byte[v.ValueSize];
- Marshal.Copy(v.Value, value, 0, (int)v.ValueSize);
-
- return new CredentialAttribute
- {
- Keyword = v.Keyword,
- Flags = v.Flags,
- Value = value,
- };
- }
- }
-
- [StructLayout(LayoutKind.Sequential)]
- public struct FILETIME
- {
- internal UInt32 dwLowDateTime;
- internal UInt32 dwHighDateTime;
-
- public static implicit operator long(FILETIME v) { return ((long)v.dwHighDateTime << 32) + v.dwLowDateTime; }
- public static explicit operator DateTimeOffset(FILETIME v) { return DateTimeOffset.FromFileTime(v); }
- public static explicit operator FILETIME(DateTimeOffset v)
- {
- return new FILETIME()
- {
- dwLowDateTime = (UInt32)v.ToFileTime(),
- dwHighDateTime = ((UInt32)v.ToFileTime() >> 32),
- };
- }
- }
-
- [Flags]
- public enum CredentialCreateFlags : uint
- {
- PreserveCredentialBlob = 1,
- }
-
- [Flags]
- public enum CredentialFlags
- {
- None = 0,
- PromptNow = 2,
- UsernameTarget = 4,
- }
-
- public enum CredMarshalType : uint
- {
- CertCredential = 1,
- UsernameTargetCredential,
- BinaryBlobCredential,
- UsernameForPackedCredential,
- BinaryBlobForSystem,
- }
- }
-
- internal class NativeMethods
- {
- [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool CredDeleteW(
- [MarshalAs(UnmanagedType.LPWStr)] string TargetName,
- CredentialType Type,
- UInt32 Flags);
-
- [DllImport("advapi32.dll")]
- public static extern void CredFree(
- IntPtr Buffer);
-
- [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool CredMarshalCredentialW(
- NativeHelpers.CredMarshalType CredType,
- SafeMemoryBuffer Credential,
- out SafeCredentialBuffer MarshaledCredential);
-
- [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool CredReadW(
- [MarshalAs(UnmanagedType.LPWStr)] string TargetName,
- CredentialType Type,
- UInt32 Flags,
- out SafeCredentialBuffer Credential);
-
- [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool CredUnmarshalCredentialW(
- [MarshalAs(UnmanagedType.LPWStr)] string MarshaledCredential,
- out NativeHelpers.CredMarshalType CredType,
- out SafeCredentialBuffer Credential);
-
- [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool CredWriteW(
- NativeHelpers.CREDENTIAL Credential,
- NativeHelpers.CredentialCreateFlags Flags);
- }
-
- internal class SafeCredentialBuffer : SafeHandleZeroOrMinusOneIsInvalid
- {
- public SafeCredentialBuffer() : base(true) { }
-
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
- protected override bool ReleaseHandle()
- {
- NativeMethods.CredFree(handle);
- return true;
- }
- }
-
- internal class SafeMemoryBuffer : SafeHandleZeroOrMinusOneIsInvalid
- {
- public SafeMemoryBuffer() : base(true) { }
- public SafeMemoryBuffer(int cb) : base(true)
- {
- base.SetHandle(Marshal.AllocHGlobal(cb));
- }
- public SafeMemoryBuffer(IntPtr handle) : base(true)
- {
- base.SetHandle(handle);
- }
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
- protected override bool ReleaseHandle()
- {
- Marshal.FreeHGlobal(handle);
- return true;
- }
- }
-
- public class Win32Exception : System.ComponentModel.Win32Exception
- {
- private string _exception_msg;
- public Win32Exception(string message) : this(Marshal.GetLastWin32Error(), message) { }
- public Win32Exception(int errorCode, string message) : base(errorCode)
- {
- _exception_msg = String.Format("{0} - {1} (Win32 Error Code {2}: 0x{3})", message, base.Message, errorCode, errorCode.ToString("X8"));
- }
- public override string Message { get { return _exception_msg; } }
- public static explicit operator Win32Exception(string message) { return new Win32Exception(message); }
- }
-
- public enum CredentialPersist
- {
- Session = 1,
- LocalMachine = 2,
- Enterprise = 3,
- }
-
- public enum CredentialType
- {
- Generic = 1,
- DomainPassword = 2,
- DomainCertificate = 3,
- DomainVisiblePassword = 4,
- GenericCertificate = 5,
- DomainExtended = 6,
- Maximum = 7,
- MaximumEx = 1007,
- }
-
- public class CredentialAttribute
- {
- public string Keyword;
- public UInt32 Flags;
- public byte[] Value;
- }
-
- public class Credential
- {
- public CredentialType Type;
- public string TargetName;
- public string Comment;
- public DateTimeOffset LastWritten;
- public byte[] Secret;
- public CredentialPersist Persist;
- public List<CredentialAttribute> Attributes = new List<CredentialAttribute>();
- public string TargetAlias;
- public string UserName;
-
- // Used to track whether the credential has been loaded into the store or not
- public bool Loaded { get; internal set; }
-
- public void Delete()
- {
- if (!Loaded)
- return;
-
- if (!NativeMethods.CredDeleteW(TargetName, Type, 0))
- throw new Win32Exception(String.Format("CredDeleteW({0}) failed", TargetName));
- Loaded = false;
- }
-
- public void Write(bool preserveExisting)
- {
- string userName = UserName;
- // Convert the certificate thumbprint to the string expected
- if (Type == CredentialType.DomainCertificate || Type == CredentialType.GenericCertificate)
- userName = Credential.MarshalCertificateCredential(userName);
-
- NativeHelpers.CREDENTIAL credential = new NativeHelpers.CREDENTIAL
- {
- Flags = NativeHelpers.CredentialFlags.None,
- Type = Type,
- TargetName = TargetName,
- Comment = Comment,
- LastWritten = new NativeHelpers.FILETIME(),
- CredentialBlobSize = (UInt32)(Secret == null ? 0 : Secret.Length),
- CredentialBlob = IntPtr.Zero, // Must be allocated and freed outside of this to ensure no memory leaks
- Persist = Persist,
- AttributeCount = (UInt32)(Attributes.Count),
- Attributes = IntPtr.Zero, // Attributes must be allocated and freed outside of this to ensure no memory leaks
- TargetAlias = TargetAlias,
- UserName = userName,
- };
-
- using (SafeMemoryBuffer credentialBlob = new SafeMemoryBuffer((int)credential.CredentialBlobSize))
- {
- if (Secret != null)
- Marshal.Copy(Secret, 0, credentialBlob.DangerousGetHandle(), Secret.Length);
- credential.CredentialBlob = credentialBlob.DangerousGetHandle();
-
- // Store the CREDENTIAL_ATTRIBUTE value in a safe memory buffer and make sure we dispose in all cases
- List<SafeMemoryBuffer> attributeBuffers = new List<SafeMemoryBuffer>();
- try
- {
- int attributeLength = Attributes.Sum(a => Marshal.SizeOf(typeof(NativeHelpers.CREDENTIAL_ATTRIBUTE)));
- byte[] attributeBytes = new byte[attributeLength];
- int offset = 0;
- foreach (CredentialAttribute attribute in Attributes)
- {
- SafeMemoryBuffer attributeBuffer = new SafeMemoryBuffer(attribute.Value.Length);
- attributeBuffers.Add(attributeBuffer);
- if (attribute.Value != null)
- Marshal.Copy(attribute.Value, 0, attributeBuffer.DangerousGetHandle(), attribute.Value.Length);
-
- NativeHelpers.CREDENTIAL_ATTRIBUTE credentialAttribute = new NativeHelpers.CREDENTIAL_ATTRIBUTE
- {
- Keyword = attribute.Keyword,
- Flags = attribute.Flags,
- ValueSize = (UInt32)(attribute.Value == null ? 0 : attribute.Value.Length),
- Value = attributeBuffer.DangerousGetHandle(),
- };
- int attributeStructLength = Marshal.SizeOf(typeof(NativeHelpers.CREDENTIAL_ATTRIBUTE));
-
- byte[] attrBytes = new byte[attributeStructLength];
- using (SafeMemoryBuffer tempBuffer = new SafeMemoryBuffer(attributeStructLength))
- {
- Marshal.StructureToPtr(credentialAttribute, tempBuffer.DangerousGetHandle(), false);
- Marshal.Copy(tempBuffer.DangerousGetHandle(), attrBytes, 0, attributeStructLength);
- }
- Buffer.BlockCopy(attrBytes, 0, attributeBytes, offset, attributeStructLength);
- offset += attributeStructLength;
- }
-
- using (SafeMemoryBuffer attributes = new SafeMemoryBuffer(attributeBytes.Length))
- {
- if (attributeBytes.Length != 0)
- {
- Marshal.Copy(attributeBytes, 0, attributes.DangerousGetHandle(), attributeBytes.Length);
- credential.Attributes = attributes.DangerousGetHandle();
- }
-
- NativeHelpers.CredentialCreateFlags createFlags = 0;
- if (preserveExisting)
- createFlags |= NativeHelpers.CredentialCreateFlags.PreserveCredentialBlob;
-
- if (!NativeMethods.CredWriteW(credential, createFlags))
- throw new Win32Exception(String.Format("CredWriteW({0}) failed", TargetName));
- }
- }
- finally
- {
- foreach (SafeMemoryBuffer attributeBuffer in attributeBuffers)
- attributeBuffer.Dispose();
- }
- }
- Loaded = true;
- }
-
- public static Credential GetCredential(string target, CredentialType type)
- {
- SafeCredentialBuffer buffer;
- if (!NativeMethods.CredReadW(target, type, 0, out buffer))
- {
- int lastErr = Marshal.GetLastWin32Error();
-
- // Not running with Become so cannot manage the user's credentials
- if (lastErr == 0x00000520) // ERROR_NO_SUCH_LOGON_SESSION
- throw new InvalidOperationException("Failed to access the user's credential store, run the module with become");
- else if (lastErr == 0x00000490) // ERROR_NOT_FOUND
- return null;
- throw new Win32Exception(lastErr, "CredEnumerateW() failed");
- }
-
- using (buffer)
- {
- NativeHelpers.CREDENTIAL credential = (NativeHelpers.CREDENTIAL)Marshal.PtrToStructure(
- buffer.DangerousGetHandle(), typeof(NativeHelpers.CREDENTIAL));
- return (Credential)credential;
- }
- }
-
- public static string MarshalCertificateCredential(string thumbprint)
- {
- // CredWriteW requires the UserName field to be the value of CredMarshalCredentialW() when writting a
- // certificate auth. This converts the UserName property to the format required.
-
- // While CERT_CREDENTIAL_INFO is the correct structure, we manually marshal the data in order to
- // support different cert hash lengths in the future.
- // https://docs.microsoft.com/en-us/windows/desktop/api/wincred/ns-wincred-_cert_credential_info
- int hexLength = thumbprint.Length;
- byte[] credInfo = new byte[sizeof(UInt32) + (hexLength / 2)];
-
- // First field is cbSize which is a UInt32 value denoting the size of the total structure
- Array.Copy(BitConverter.GetBytes((UInt32)credInfo.Length), credInfo, sizeof(UInt32));
-
- // Now copy the byte representation of the thumbprint to the rest of the struct bytes
- for (int i = 0; i < hexLength; i += 2)
- credInfo[sizeof(UInt32) + (i / 2)] = Convert.ToByte(thumbprint.Substring(i, 2), 16);
-
- IntPtr pCredInfo = Marshal.AllocHGlobal(credInfo.Length);
- Marshal.Copy(credInfo, 0, pCredInfo, credInfo.Length);
- SafeMemoryBuffer pCredential = new SafeMemoryBuffer(pCredInfo);
-
- NativeHelpers.CredMarshalType marshalType = NativeHelpers.CredMarshalType.CertCredential;
- using (pCredential)
- {
- SafeCredentialBuffer marshaledCredential;
- if (!NativeMethods.CredMarshalCredentialW(marshalType, pCredential, out marshaledCredential))
- throw new Win32Exception("CredMarshalCredentialW() failed");
- using (marshaledCredential)
- return Marshal.PtrToStringUni(marshaledCredential.DangerousGetHandle());
- }
- }
-
- public static string UnmarshalCertificateCredential(string value)
- {
- NativeHelpers.CredMarshalType credType;
- SafeCredentialBuffer pCredInfo;
- if (!NativeMethods.CredUnmarshalCredentialW(value, out credType, out pCredInfo))
- throw new Win32Exception("CredUnmarshalCredentialW() failed");
-
- using (pCredInfo)
- {
- if (credType != NativeHelpers.CredMarshalType.CertCredential)
- throw new InvalidOperationException(String.Format("Expected unmarshalled cred type of CertCredential, received {0}", credType));
-
- byte[] structSizeBytes = new byte[sizeof(UInt32)];
- Marshal.Copy(pCredInfo.DangerousGetHandle(), structSizeBytes, 0, sizeof(UInt32));
- UInt32 structSize = BitConverter.ToUInt32(structSizeBytes, 0);
-
- byte[] certInfoBytes = new byte[structSize];
- Marshal.Copy(pCredInfo.DangerousGetHandle(), certInfoBytes, 0, certInfoBytes.Length);
-
- StringBuilder hex = new StringBuilder((certInfoBytes.Length - sizeof(UInt32)) * 2);
- for (int i = 4; i < certInfoBytes.Length; i++)
- hex.AppendFormat("{0:x2}", certInfoBytes[i]);
-
- return hex.ToString().ToUpperInvariant();
- }
- }
-
- internal static void PtrToStructureArray<T>(T[] array, IntPtr ptr)
- {
- IntPtr ptrOffset = ptr;
- for (int i = 0; i < array.Length; i++, ptrOffset = IntPtr.Add(ptrOffset, Marshal.SizeOf(typeof(T))))
- array[i] = (T)Marshal.PtrToStructure(ptrOffset, typeof(T));
- }
- }
-}
-'@
-
-Function ConvertTo-CredentialAttribute {
- param($Attributes)
-
- $converted_attributes = [System.Collections.Generic.List`1[Ansible.CredentialManager.CredentialAttribute]]@()
- foreach ($attribute in $Attributes) {
- $new_attribute = New-Object -TypeName Ansible.CredentialManager.CredentialAttribute
- $new_attribute.Keyword = $attribute.name
-
- if ($null -ne $attribute.data) {
- if ($attribute.data_format -eq "base64") {
- $new_attribute.Value = [System.Convert]::FromBase64String($attribute.data)
- } else {
- $new_attribute.Value = [System.Text.Encoding]::UTF8.GetBytes($attribute.data)
- }
- }
- $converted_attributes.Add($new_attribute) > $null
- }
-
- return ,$converted_attributes
-}
-
-Function Get-DiffInfo {
- param($AnsibleCredential)
-
- $diff = @{
- alias = $AnsibleCredential.TargetAlias
- attributes = [System.Collections.ArrayList]@()
- comment = $AnsibleCredential.Comment
- name = $AnsibleCredential.TargetName
- persistence = $AnsibleCredential.Persist.ToString()
- type = $AnsibleCredential.Type.ToString()
- username = $AnsibleCredential.UserName
- }
-
- foreach ($attribute in $AnsibleCredential.Attributes) {
- $attribute_info = @{
- name = $attribute.Keyword
- data = $null
- }
- if ($null -ne $attribute.Value) {
- $attribute_info.data = [System.Convert]::ToBase64String($attribute.Value)
- }
- $diff.attributes.Add($attribute_info) > $null
- }
-
- return ,$diff
-}
-
-# If the username is a certificate thumbprint, verify it's a valid cert in the CurrentUser/Personal store
-if ($null -ne $username -and $type -in @("domain_certificate", "generic_certificate")) {
- # Ensure the thumbprint is upper case with no spaces or hyphens
- $username = $username.ToUpperInvariant().Replace(" ", "").Replace("-", "")
-
- $certificate = Get-Item -Path Cert:\CurrentUser\My\$username -ErrorAction SilentlyContinue
- if ($null -eq $certificate) {
- $module.FailJson("Failed to find certificate with the thumbprint $username in the CurrentUser\My store")
- }
-}
-
-# Convert the input secret to a byte array
-if ($null -ne $secret) {
- if ($secret_format -eq "base64") {
- $secret = [System.Convert]::FromBase64String($secret)
- } else {
- $secret = [System.Text.Encoding]::Unicode.GetBytes($secret)
- }
-}
-
-$persistence = switch ($persistence) {
- "local" { [Ansible.CredentialManager.CredentialPersist]::LocalMachine }
- "enterprise" { [Ansible.CredentialManager.CredentialPersist]::Enterprise }
-}
-
-$type = switch ($type) {
- "domain_password" { [Ansible.CredentialManager.CredentialType]::DomainPassword }
- "domain_certificate" { [Ansible.CredentialManager.CredentialType]::DomainCertificate }
- "generic_password" { [Ansible.CredentialManager.CredentialType]::Generic }
- "generic_certificate" { [Ansible.CredentialManager.CredentialType]::GenericCertificate }
-}
-
-$existing_credential = [Ansible.CredentialManager.Credential]::GetCredential($name, $type)
-if ($null -ne $existing_credential) {
- $module.Diff.before = Get-DiffInfo -AnsibleCredential $existing_credential
-}
-
-if ($state -eq "absent") {
- if ($null -ne $existing_credential) {
- if (-not $module.CheckMode) {
- $existing_credential.Delete()
- }
- $module.Result.changed = $true
- }
-} else {
- if ($null -eq $existing_credential) {
- $new_credential = New-Object -TypeName Ansible.CredentialManager.Credential
- $new_credential.Type = $type
- $new_credential.TargetName = $name
- $new_credential.Comment = if ($comment) { $comment } else { [NullString]::Value }
- $new_credential.Secret = $secret
- $new_credential.Persist = $persistence
- $new_credential.TargetAlias = if ($alias) { $alias } else { [NullString]::Value }
- $new_credential.UserName = $username
-
- if ($null -ne $attributes) {
- $new_credential.Attributes = ConvertTo-CredentialAttribute -Attributes $attributes
- }
-
- if (-not $module.CheckMode) {
- $new_credential.Write($false)
- }
- $module.Result.changed = $true
- } else {
- $changed = $false
- $preserve_blob = $false
-
- # make sure we do case comparison for the comment
- if ($existing_credential.Comment -cne $comment) {
- $existing_credential.Comment = $comment
- $changed = $true
- }
-
- if ($existing_credential.Persist -ne $persistence) {
- $existing_credential.Persist = $persistence
- $changed = $true
- }
-
- if ($existing_credential.TargetAlias -ne $alias) {
- $existing_credential.TargetAlias = $alias
- $changed = $true
- }
-
- if ($existing_credential.UserName -ne $username) {
- $existing_credential.UserName = $username
- $changed = $true
- }
-
- if ($null -ne $attributes) {
- $attribute_changed = $false
-
- $new_attributes = ConvertTo-CredentialAttribute -Attributes $attributes
- if ($new_attributes.Count -ne $existing_credential.Attributes.Count) {
- $attribute_changed = $true
- } else {
- for ($i = 0; $i -lt $new_attributes.Count; $i++) {
- $new_keyword = $new_attributes[$i].Keyword
- $new_value = $new_attributes[$i].Value
- if ($null -eq $new_value) {
- $new_value = ""
- } else {
- $new_value = [System.Convert]::ToBase64String($new_value)
- }
-
- $existing_keyword = $existing_credential.Attributes[$i].Keyword
- $existing_value = $existing_credential.Attributes[$i].Value
- if ($null -eq $existing_value) {
- $existing_value = ""
- } else {
- $existing_value = [System.Convert]::ToBase64String($existing_value)
- }
-
- if (($new_keyword -cne $existing_keyword) -or ($new_value -ne $existing_value)) {
- $attribute_changed = $true
- break
- }
- }
- }
-
- if ($attribute_changed) {
- $existing_credential.Attributes = $new_attributes
- $changed = $true
- }
- }
-
- if ($null -eq $secret) {
- # If we haven't explicitly set a secret, tell Windows to preserve the existing blob
- $preserve_blob = $true
- $existing_credential.Secret = $null
- } elseif ($update_secret -eq "always") {
- # We should only set the password if we can't read the existing one or it doesn't match our secret
- if ($existing_credential.Secret.Length -eq 0) {
- # We cannot read the secret so don't know if its the configured secret
- $existing_credential.Secret = $secret
- $changed = $true
- } else {
- # We can read the secret so compare with our input
- $input_secret_b64 = [System.Convert]::ToBase64String($secret)
- $actual_secret_b64 = [System.Convert]::ToBase64String($existing_credential.Secret)
- if ($input_secret_b64 -ne $actual_secret_b64) {
- $existing_credential.Secret = $secret
- $changed = $true
- }
- }
- }
-
- if ($changed -and -not $module.CheckMode) {
- $existing_credential.Write($preserve_blob)
- }
- $module.Result.changed = $changed
- }
-
- if ($module.CheckMode) {
- # We cannot reliably get the credential in check mode, set it based on the input
- $module.Diff.after = @{
- alias = $alias
- attributes = $attributes
- comment = $comment
- name = $name
- persistence = $persistence.ToString()
- type = $type.ToString()
- username = $username
- }
- } else {
- # Get a new copy of the credential and use that to set the after diff
- $new_credential = [Ansible.CredentialManager.Credential]::GetCredential($name, $type)
- $module.Diff.after = Get-DiffInfo -AnsibleCredential $new_credential
- }
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_credential.py b/lib/ansible/modules/windows/win_credential.py
deleted file mode 100644
index 57cbb483af..0000000000
--- a/lib/ansible/modules/windows/win_credential.py
+++ /dev/null
@@ -1,209 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_credential
-version_added: '2.8'
-short_description: Manages Windows Credentials in the Credential Manager
-description:
-- Used to create and remove Windows Credentials in the Credential Manager.
-- This module can manage both standard username/password credentials as well as
- certificate credentials.
-options:
- alias:
- description:
- - Adds an alias for the credential.
- - Typically this is the NetBIOS name of a host if I(name) is set to the DNS
- name.
- type: str
- attributes:
- description:
- - A list of dicts that set application specific attributes for a
- credential.
- - When set, existing attributes will be compared to the list as a whole,
- any differences means all attributes will be replaced.
- suboptions:
- name:
- description:
- - The key for the attribute.
- - This is not a unique identifier as multiple attributes can have the
- same key.
- type: str
- required: true
- data:
- description:
- - The value for the attribute.
- type: str
- data_format:
- description:
- - Controls the input type for I(data).
- - If C(text), I(data) is a text string that is UTF-16LE encoded to
- bytes.
- - If C(base64), I(data) is a base64 string that is base64 decoded to
- bytes.
- type: str
- choices: [ base64, text ]
- default: text
- comment:
- description:
- - A user defined comment for the credential.
- type: str
- name:
- description:
- - The target that identifies the server or servers that the credential is
- to be used for.
- - If the value can be a NetBIOS name, DNS server name, DNS host name suffix
- with a wildcard character (C(*)), a NetBIOS of DNS domain name that
- contains a wildcard character sequence, or an asterisk.
- - See C(TargetName) in U(https://docs.microsoft.com/en-us/windows/desktop/api/wincred/ns-wincred-_credentiala)
- for more details on what this value can be.
- - This is used with I(type) to produce a unique credential.
- type: str
- required: true
- persistence:
- description:
- - Defines the persistence of the credential.
- - If C(local), the credential will persist for all logons of the same user
- on the same host.
- - C(enterprise) is the same as C(local) but the credential is visible to
- the same domain user when running on other hosts and not just localhost.
- type: str
- choices: [ enterprise, local ]
- default: local
- secret:
- description:
- - The secret for the credential.
- - When omitted, then no secret is used for the credential if a new
- credentials is created.
- - When I(type) is a password type, this is the password for I(username).
- - When I(type) is a certificate type, this is the pin for the certificate.
- type: str
- secret_format:
- description:
- - Controls the input type for I(secret).
- - If C(text), I(secret) is a text string that is UTF-16LE encoded to bytes.
- - If C(base64), I(secret) is a base64 string that is base64 decoded to
- bytes.
- type: str
- choices: [ base64, text ]
- default: text
- state:
- description:
- - When C(absent), the credential specified by I(name) and I(type) is
- removed.
- - When C(present), the credential specified by I(name) and I(type) is
- removed.
- type: str
- choices: [ absent, present ]
- default: present
- type:
- description:
- - The type of credential to store.
- - This is used with I(name) to produce a unique credential.
- - When the type is a C(domain) type, the credential is used by Microsoft
- authentication packages like Negotiate.
- - When the type is a C(generic) type, the credential is not used by any
- particular authentication package.
- - It is recommended to use a C(domain) type as only authentication
- providers can access the secret.
- type: str
- required: true
- choices: [ domain_certificate, domain_password, generic_certificate, generic_password ]
- update_secret:
- description:
- - When C(always), the secret will always be updated if they differ.
- - When C(on_create), the secret will only be checked/updated when it is
- first created.
- - If the secret cannot be retrieved and this is set to C(always), the
- module will always result in a change.
- type: str
- choices: [ always, on_create ]
- default: always
- username:
- description:
- - When I(type) is a password type, then this is the username to store for
- the credential.
- - When I(type) is a credential type, then this is the thumbprint as a hex
- string of the certificate to use.
- - When C(type=domain_password), this should be in the form of a Netlogon
- (DOMAIN\Username) or a UPN (username@DOMAIN).
- - If using a certificate thumbprint, the certificate must exist in the
- C(CurrentUser\My) certificate store for the executing user.
- type: str
-notes:
-- This module requires to be run with C(become) so it can access the
- user's credential store.
-- There can only be one credential per host and type. if a second credential is
- defined that uses the same host and type, then the original credential is
- overwritten.
-seealso:
-- module: win_user_right
-- module: win_whoami
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Create a local only credential
- win_credential:
- name: server.domain.com
- type: domain_password
- username: DOMAIN\username
- secret: Password01
- state: present
-
-- name: Remove a credential
- win_credential:
- name: server.domain.com
- type: domain_password
- state: absent
-
-- name: Create a credential with full values
- win_credential:
- name: server.domain.com
- type: domain_password
- alias: server
- username: username@DOMAIN.COM
- secret: Password01
- comment: Credential for server.domain.com
- persistence: enterprise
- attributes:
- - name: Source
- data: Ansible
- - name: Unique Identifier
- data: Y3VzdG9tIGF0dHJpYnV0ZQ==
- data_format: base64
-
-- name: Create a certificate credential
- win_credential:
- name: '*.domain.com'
- type: domain_certificate
- username: 0074CC4F200D27DC3877C24A92BA8EA21E6C7AF4
- state: present
-
-- name: Create a generic credential
- win_credential:
- name: smbhost
- type: generic_password
- username: smbuser
- secret: smbuser
- state: present
-
-- name: Remove a generic credential
- win_credential:
- name: smbhost
- type: generic_password
- state: absent
-'''
-
-RETURN = r'''
-#
-'''
diff --git a/lib/ansible/modules/windows/win_data_deduplication.ps1 b/lib/ansible/modules/windows/win_data_deduplication.ps1
deleted file mode 100644
index 593ee76381..0000000000
--- a/lib/ansible/modules/windows/win_data_deduplication.ps1
+++ /dev/null
@@ -1,129 +0,0 @@
-#!powershell
-
-# Copyright: 2019, rnsc(@rnsc) <github@rnsc.be>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#AnsibleRequires -OSVersion 6.3
-
-$spec = @{
- options = @{
- drive_letter = @{ type = "str"; required = $true }
- state = @{ type = "str"; choices = "absent", "present"; default = "present"; }
- settings = @{
- type = "dict"
- required = $false
- options = @{
- minimum_file_size = @{ type = "int"; default = 32768 }
- minimum_file_age_days = @{ type = "int"; default = 2 }
- no_compress = @{ type = "bool"; required = $false; default = $false }
- optimize_in_use_files = @{ type = "bool"; required = $false; default = $false }
- verify = @{ type = "bool"; required = $false; default = $false }
- }
- }
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$drive_letter = $module.Params.drive_letter
-$state = $module.Params.state
-$settings = $module.Params.settings
-
-$module.Result.changed = $false
-$module.Result.reboot_required = $false
-$module.Result.msg = ""
-
-function Set-DataDeduplication($volume, $state, $settings, $dedup_job) {
-
- $current_state = 'absent'
-
- try {
- $dedup_info = Get-DedupVolume -Volume "$($volume.DriveLetter):"
- } catch {
- $dedup_info = $null
- }
-
- if ($dedup_info.Enabled) {
- $current_state = 'present'
- }
-
- if ( $state -ne $current_state ) {
- if( -not $module.CheckMode) {
- if($state -eq 'present') {
- # Enable-DedupVolume -Volume <String>
- Enable-DedupVolume -Volume "$($volume.DriveLetter):"
- } elseif ($state -eq 'absent') {
- Disable-DedupVolume -Volume "$($volume.DriveLetter):"
- }
- }
- $module.Result.changed = $true
- }
-
- if ($state -eq 'present') {
- if ($null -ne $settings) {
- Set-DataDedupJobSettings -volume $volume -settings $settings
- }
- }
-}
-
-function Set-DataDedupJobSettings ($volume, $settings) {
-
- try {
- $dedup_info = Get-DedupVolume -Volume "$($volume.DriveLetter):"
- } catch {
- $dedup_info = $null
- }
-
- ForEach ($key in $settings.keys) {
-
- # See Microsoft documentation:
- # https://docs.microsoft.com/en-us/powershell/module/deduplication/set-dedupvolume?view=win10-ps
-
- $update_key = $key
- $update_value = $settings.$($key)
- # Transform Ansible style options to Powershell params
- $update_key = $update_key -replace('_', '')
-
- if ($update_key -eq "MinimumFileSize" -and $update_value -lt 32768) {
- $update_value = 32768
- }
-
- $current_value = ($dedup_info | Select-Object -ExpandProperty $update_key)
-
- if ($update_value -ne $current_value) {
- $command_param = @{
- $($update_key) = $update_value
- }
-
- # Set-DedupVolume -Volume <String>`
- # -NoCompress <bool> `
- # -MinimumFileAgeDays <UInt32> `
- # -MinimumFileSize <UInt32> (minimum 32768)
- if( -not $module.CheckMode ) {
- Set-DedupVolume -Volume "$($volume.DriveLetter):" @command_param
- }
-
- $module.Result.changed = $true
- }
- }
-
-}
-
-# Install required feature
-$feature_name = "FS-Data-Deduplication"
-if( -not $module.CheckMode) {
- $feature = Install-WindowsFeature -Name $feature_name
-
- if ($feature.RestartNeeded -eq 'Yes') {
- $module.Result.reboot_required = $true
- $module.FailJson("$feature_name was installed but requires Windows to be rebooted to work.")
- }
-}
-
-$volume = Get-Volume -DriveLetter $drive_letter
-
-Set-DataDeduplication -volume $volume -state $state -settings $settings -dedup_job $dedup_job
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_data_deduplication.py b/lib/ansible/modules/windows/win_data_deduplication.py
deleted file mode 100644
index d320b9f7c2..0000000000
--- a/lib/ansible/modules/windows/win_data_deduplication.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: 2019, rnsc(@rnsc) <github@rnsc.be>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_data_deduplication
-version_added: "2.10"
-short_description: Module to enable Data Deduplication on a volume.
-description:
-- This module can be used to enable Data Deduplication on a Windows volume.
-- The module will install the FS-Data-Deduplication feature (a reboot will be necessary).
-options:
- drive_letter:
- description:
- - Windows drive letter on which to enable data deduplication.
- required: yes
- type: str
- state:
- description:
- - Wether to enable or disable data deduplication on the selected volume.
- default: present
- type: str
- choices: [ present, absent ]
- settings:
- description:
- - Dictionary of settings to pass to the Set-DedupVolume powershell command.
- type: dict
- suboptions:
- minimum_file_size:
- description:
- - Minimum file size you want to target for deduplication.
- - It will default to 32768 if not defined or if the value is less than 32768.
- type: int
- default: 32768
- minimum_file_age_days:
- description:
- - Minimum file age you want to target for deduplication.
- type: int
- default: 2
- no_compress:
- description:
- - Wether you want to enabled filesystem compression or not.
- type: bool
- default: no
- optimize_in_use_files:
- description:
- - Indicates that the server attempts to optimize currently open files.
- type: bool
- default: no
- verify:
- description:
- - Indicates whether the deduplication engine performs a byte-for-byte verification for each duplicate chunk
- that optimization creates, rather than relying on a cryptographically strong hash.
- - This option is not recommend.
- - Setting this parameter to True can degrade optimization performance.
- type: bool
- default: no
-author:
-- rnsc (@rnsc)
-'''
-
-EXAMPLES = r'''
-- name: Enable Data Deduplication on D
- win_data_deduplication:
- drive_letter: 'D'
- state: present
-
-- name: Enable Data Deduplication on D
- win_data_deduplication:
- drive_letter: 'D'
- state: present
- settings:
- no_compress: true
- minimum_file_age_days: 1
- minimum_file_size: 0
-'''
-
-RETURN = r'''
-#
-'''
diff --git a/lib/ansible/modules/windows/win_defrag.ps1 b/lib/ansible/modules/windows/win_defrag.ps1
deleted file mode 100644
index b88b4ef252..0000000000
--- a/lib/ansible/modules/windows/win_defrag.ps1
+++ /dev/null
@@ -1,97 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.ArgvParser
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-
-$spec = @{
- options = @{
- include_volumes = @{ type='list' }
- exclude_volumes = @{ type='list' }
- freespace_consolidation = @{ type='bool'; default=$false }
- priority = @{ type='str'; default='low'; choices=@( 'low', 'normal') }
- parallel = @{ type='bool'; default=$false }
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$include_volumes = $module.Params.include_volumes
-$exclude_volumes = $module.Params.exclude_volumes
-$freespace_consolidation = $module.Params.freespace_consolidation
-$priority = $module.Params.priority
-$parallel = $module.Params.parallel
-
-$module.Result.changed = $false
-
-$executable = "defrag.exe"
-
-if (-not (Get-Command -Name $executable -ErrorAction SilentlyContinue)) {
- $module.FailJson("Command '$executable' not found in $env:PATH.")
-}
-
-$arguments = @()
-
-if ($include_volumes) {
- foreach ($volume in $include_volumes) {
- if ($volume.Length -eq 1) {
- $arguments += "$($volume):"
- } else {
- $arguments += $volume
- }
- }
-} else {
- $arguments += "/C"
-}
-
-if ($exclude_volumes) {
- $arguments += "/E"
- foreach ($volume in $exclude_volumes) {
- if ($volume.Length -eq 1) {
- $arguments += "$($volume):"
- } else {
- $arguments += $volume
- }
- }
-}
-
-if ($module.CheckMode) {
- $arguments += "/A"
-} elseif ($freespace_consolidation) {
- $arguments += "/X"
-}
-
-if ($priority -eq "normal") {
- $arguments += "/H"
-}
-
-if ($parallel) {
- $arguments += "/M"
-}
-
-$arguments += "/V"
-
-$argument_string = Argv-ToString -arguments $arguments
-
-$start_datetime = [DateTime]::UtcNow
-$module.Result.cmd = "$executable $argument_string"
-
-$command_result = Run-Command -command "$executable $argument_string"
-
-$end_datetime = [DateTime]::UtcNow
-
-$module.Result.stdout = $command_result.stdout
-$module.Result.stderr = $command_result.stderr
-$module.Result.rc = $command_result.rc
-
-$module.Result.start = $start_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
-$module.Result.end = $end_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
-$module.Result.delta = $($end_datetime - $start_datetime).ToString("h\:mm\:ss\.ffffff")
-
-$module.Result.changed = $true
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_defrag.py b/lib/ansible/modules/windows/win_defrag.py
deleted file mode 100644
index 6889dfb7dc..0000000000
--- a/lib/ansible/modules/windows/win_defrag.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_defrag
-version_added: '2.4'
-short_description: Consolidate fragmented files on local volumes
-description:
-- Locates and consolidates fragmented files on local volumes to improve system performance.
-- 'More information regarding C(win_defrag) is available from: U(https://technet.microsoft.com/en-us/library/cc731650(v=ws.11).aspx)'
-requirements:
-- defrag.exe
-options:
- include_volumes:
- description:
- - A list of drive letters or mount point paths of the volumes to be defragmented.
- - If this parameter is omitted, all volumes (not excluded) will be fragmented.
- type: list
- exclude_volumes:
- description:
- - A list of drive letters or mount point paths to exclude from defragmentation.
- type: list
- freespace_consolidation:
- description:
- - Perform free space consolidation on the specified volumes.
- type: bool
- default: no
- priority:
- description:
- - Run the operation at low or normal priority.
- type: str
- choices: [ low, normal ]
- default: low
- parallel:
- description:
- - Run the operation on each volume in parallel in the background.
- type: bool
- default: no
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-EXAMPLES = r'''
-- name: Defragment all local volumes (in parallel)
- win_defrag:
- parallel: yes
-
-- name: 'Defragment all local volumes, except C: and D:'
- win_defrag:
- exclude_volumes: [ C, D ]
-
-- name: 'Defragment volume D: with normal priority'
- win_defrag:
- include_volumes: D
- priority: normal
-
-- name: Consolidate free space (useful when reducing volumes)
- win_defrag:
- freespace_consolidation: yes
-'''
-
-RETURN = r'''
-cmd:
- description: The complete command line used by the module.
- returned: always
- type: str
- sample: defrag.exe /C /V
-rc:
- description: The return code for the command.
- returned: always
- type: int
- sample: 0
-stdout:
- description: The standard output from the command.
- returned: always
- type: str
- sample: Success.
-stderr:
- description: The error output from the command.
- returned: always
- type: str
- sample:
-msg:
- description: Possible error message on failure.
- returned: failed
- type: str
- sample: Command 'defrag.exe' not found in $env:PATH.
-changed:
- description: Whether or not any changes were made.
- returned: always
- type: bool
- sample: true
-'''
diff --git a/lib/ansible/modules/windows/win_disk_facts.ps1 b/lib/ansible/modules/windows/win_disk_facts.ps1
deleted file mode 100644
index 30bff60c14..0000000000
--- a/lib/ansible/modules/windows/win_disk_facts.ps1
+++ /dev/null
@@ -1,251 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Marc Tschapek <marc.tschapek@itelligence.de>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#AnsibleRequires -OSVersion 6.2
-
-$ErrorActionPreference = "Stop"
-Set-StrictMode -Version 2.0
-
-# Functions
-function Test-Admin {
- $CurrentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
- $IsAdmin = $CurrentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
-
- return $IsAdmin
-}
-
-# Check admin rights
-if (-not (Test-Admin)) {
- Fail-Json -obj @{} -message "Module was not started with elevated rights"
-}
-
-# Create a new result object
-$result = @{
- changed = $false
- ansible_facts = @{
- ansible_disks = @()
- }
-}
-
-# Search disks
-try {
- $disks = Get-Disk
-} catch {
- Fail-Json -obj $result -message "Failed to search the disks on the target: $($_.Exception.Message)"
-}
-foreach ($disk in $disks) {
- $disk_info = @{}
- $pdisk = Get-PhysicalDisk -ErrorAction SilentlyContinue | Where-Object {
- $_.DeviceId -eq $disk.Number
- }
- if ($pdisk) {
- $disk_info["physical_disk"] += @{
- size = $pdisk.Size
- allocated_size = $pdisk.AllocatedSize
- device_id = $pdisk.DeviceId
- friendly_name = $pdisk.FriendlyName
- operational_status = $pdisk.OperationalStatus
- health_status = $pdisk.HealthStatus
- bus_type = $pdisk.BusType
- usage_type = $pdisk.Usage
- supported_usages = $pdisk.SupportedUsages
- spindle_speed = $pdisk.SpindleSpeed
- firmware_version = $pdisk.FirmwareVersion
- physical_location = $pdisk.PhysicalLocation
- manufacturer = $pdisk.Manufacturer
- model = $pdisk.Model
- can_pool = $pdisk.CanPool
- indication_enabled = $pdisk.IsIndicationEnabled
- partial = $pdisk.IsPartial
- serial_number = $pdisk.SerialNumber
- object_id = $pdisk.ObjectId
- unique_id = $pdisk.UniqueId
- }
- if ([single]"$([System.Environment]::OSVersion.Version.Major).$([System.Environment]::OSVersion.Version.Minor)" -ge 6.3) {
- $disk_info.physical_disk.media_type = $pdisk.MediaType
- }
- if (-not $pdisk.CanPool) {
- $disk_info.physical_disk.cannot_pool_reason = $pdisk.CannotPoolReason
- }
- $vdisk = Get-VirtualDisk -PhysicalDisk $pdisk -ErrorAction SilentlyContinue
- if ($vdisk) {
- $disk_info["virtual_disk"] += @{
- size = $vdisk.Size
- allocated_size = $vdisk.AllocatedSize
- footprint_on_pool = $vdisk.FootprintOnPool
- name = $vdisk.name
- friendly_name = $vdisk.FriendlyName
- operational_status = $vdisk.OperationalStatus
- health_status = $vdisk.HealthStatus
- provisioning_type = $vdisk.ProvisioningType
- allocation_unit_size = $vdisk.AllocationUnitSize
- media_type = $vdisk.MediaType
- parity_layout = $vdisk.ParityLayout
- access = $vdisk.Access
- detached_reason = $vdisk.DetachedReason
- write_cache_size = $vdisk.WriteCacheSize
- fault_domain_awareness = $vdisk.FaultDomainAwareness
- inter_leave = $vdisk.InterLeave
- deduplication_enabled = $vdisk.IsDeduplicationEnabled
- enclosure_aware = $vdisk.IsEnclosureAware
- manual_attach = $vdisk.IsManualAttach
- snapshot = $vdisk.IsSnapshot
- tiered = $vdisk.IsTiered
- physical_sector_size = $vdisk.PhysicalSectorSize
- logical_sector_size = $vdisk.LogicalSectorSize
- available_copies = $vdisk.NumberOfAvailableCopies
- columns = $vdisk.NumberOfColumns
- groups = $vdisk.NumberOfGroups
- physical_disk_redundancy = $vdisk.PhysicalDiskRedundancy
- read_cache_size = $vdisk.ReadCacheSize
- request_no_spof = $vdisk.RequestNoSinglePointOfFailure
- resiliency_setting_name = $vdisk.ResiliencySettingName
- object_id = $vdisk.ObjectId
- unique_id_format = $vdisk.UniqueIdFormat
- unique_id = $vdisk.UniqueId
- }
- }
- }
- $win32_disk_drive = Get-CimInstance -ClassName Win32_DiskDrive -ErrorAction SilentlyContinue | Where-Object {
- if ($_.SerialNumber) {
- $_.SerialNumber -eq $disk.SerialNumber
- } elseif ($disk.UniqueIdFormat -eq 'Vendor Specific') {
- $_.PNPDeviceID -eq $disk.UniqueId.split(':')[0]
- }
- }
- if ($win32_disk_drive) {
- $disk_info["win32_disk_drive"] += @{
- availability=$win32_disk_drive.Availability
- bytes_per_sector=$win32_disk_drive.BytesPerSector
- capabilities=$win32_disk_drive.Capabilities
- capability_descriptions=$win32_disk_drive.CapabilityDescriptions
- caption=$win32_disk_drive.Caption
- compression_method=$win32_disk_drive.CompressionMethod
- config_manager_error_code=$win32_disk_drive.ConfigManagerErrorCode
- config_manager_user_config=$win32_disk_drive.ConfigManagerUserConfig
- creation_class_name=$win32_disk_drive.CreationClassName
- default_block_size=$win32_disk_drive.DefaultBlockSize
- description=$win32_disk_drive.Description
- device_id=$win32_disk_drive.DeviceID
- error_cleared=$win32_disk_drive.ErrorCleared
- error_description=$win32_disk_drive.ErrorDescription
- error_methodology=$win32_disk_drive.ErrorMethodology
- firmware_revision=$win32_disk_drive.FirmwareRevision
- index=$win32_disk_drive.Index
- install_date=$win32_disk_drive.InstallDate
- interface_type=$win32_disk_drive.InterfaceType
- last_error_code=$win32_disk_drive.LastErrorCode
- manufacturer=$win32_disk_drive.Manufacturer
- max_block_size=$win32_disk_drive.MaxBlockSize
- max_media_size=$win32_disk_drive.MaxMediaSize
- media_loaded=$win32_disk_drive.MediaLoaded
- media_type=$win32_disk_drive.MediaType
- min_block_size=$win32_disk_drive.MinBlockSize
- model=$win32_disk_drive.Model
- name=$win32_disk_drive.Name
- needs_cleaning=$win32_disk_drive.NeedsCleaning
- number_of_media_supported=$win32_disk_drive.NumberOfMediaSupported
- partitions=$win32_disk_drive.Partitions
- pnp_device_id=$win32_disk_drive.PNPDeviceID
- power_management_capabilities=$win32_disk_drive.PowerManagementCapabilities
- power_management_supported=$win32_disk_drive.PowerManagementSupported
- scsi_bus=$win32_disk_drive.SCSIBus
- scsi_logical_unit=$win32_disk_drive.SCSILogicalUnit
- scsi_port=$win32_disk_drive.SCSIPort
- scsi_target_id=$win32_disk_drive.SCSITargetId
- sectors_per_track=$win32_disk_drive.SectorsPerTrack
- serial_number=$win32_disk_drive.SerialNumber
- signature=$win32_disk_drive.Signature
- size=$win32_disk_drive.Size
- status=$win32_disk_drive.status
- status_info=$win32_disk_drive.StatusInfo
- system_creation_class_name=$win32_disk_drive.SystemCreationClassName
- system_name=$win32_disk_drive.SystemName
- total_cylinders=$win32_disk_drive.TotalCylinders
- total_heads=$win32_disk_drive.TotalHeads
- total_sectors=$win32_disk_drive.TotalSectors
- total_tracks=$win32_disk_drive.TotalTracks
- tracks_per_cylinder=$win32_disk_drive.TracksPerCylinder
- }
- }
- $disk_info.number = $disk.Number
- $disk_info.size = $disk.Size
- $disk_info.bus_type = $disk.BusType
- $disk_info.friendly_name = $disk.FriendlyName
- $disk_info.partition_style = $disk.PartitionStyle
- $disk_info.partition_count = $disk.NumberOfPartitions
- $disk_info.operational_status = $disk.OperationalStatus
- $disk_info.sector_size = $disk.PhysicalSectorSize
- $disk_info.read_only = $disk.IsReadOnly
- $disk_info.bootable = $disk.IsBoot
- $disk_info.system_disk = $disk.IsSystem
- $disk_info.clustered = $disk.IsClustered
- $disk_info.manufacturer = $disk.Manufacturer
- $disk_info.model = $disk.Model
- $disk_info.firmware_version = $disk.FirmwareVersion
- $disk_info.location = $disk.Location
- $disk_info.serial_number = $disk.SerialNumber
- $disk_info.unique_id = $disk.UniqueId
- $disk_info.guid = $disk.Guid
- $disk_info.path = $disk.Path
- $parts = Get-Partition -DiskNumber $($disk.Number) -ErrorAction SilentlyContinue
- if ($parts) {
- $disk_info["partitions"] += @()
- foreach ($part in $parts) {
- $partition_info = @{
- number = $part.PartitionNumber
- size = $part.Size
- type = $part.Type
- drive_letter = $part.DriveLetter
- transition_state = $part.TransitionState
- offset = $part.Offset
- hidden = $part.IsHidden
- shadow_copy = $part.IsShadowCopy
- guid = $part.Guid
- access_paths = $part.AccessPaths
- }
- if ($disks.PartitionStyle -eq "GPT") {
- $partition_info.gpt_type = $part.GptType
- $partition_info.no_default_driveletter = $part.NoDefaultDriveLetter
- } elseif ($disks.PartitionStyle -eq "MBR") {
- $partition_info.mbr_type = $part.MbrType
- $partition_info.active = $part.IsActive
- }
- $vols = Get-Volume -Partition $part -ErrorAction SilentlyContinue
- if ($vols) {
- $partition_info["volumes"] += @()
- foreach ($vol in $vols) {
- $volume_info = @{
- size = $vol.Size
- size_remaining = $vol.SizeRemaining
- type = $vol.FileSystem
- label = $vol.FileSystemLabel
- health_status = $vol.HealthStatus
- drive_type = $vol.DriveType
- object_id = $vol.ObjectId
- path = $vol.Path
- }
- if ([System.Environment]::OSVersion.Version.Major -ge 10) {
- $volume_info.allocation_unit_size = $vol.AllocationUnitSize
- } else {
- $volPath = ($vol.Path.TrimStart("\\?\")).TrimEnd("\")
- $BlockSize = (Get-CimInstance -Query "SELECT BlockSize FROM Win32_Volume WHERE DeviceID like '%$volPath%'" -ErrorAction SilentlyContinue | Select-Object BlockSize).BlockSize
- $volume_info.allocation_unit_size = $BlockSize
- }
- $partition_info.volumes += $volume_info
- }
- }
- $disk_info.partitions += $partition_info
- }
- }
- $result.ansible_facts.ansible_disks += $disk_info
-}
-
-# Sort by disk number property
-$result.ansible_facts.ansible_disks = @() + ($result.ansible_facts.ansible_disks | Sort-Object -Property {$_.Number})
-
-# Return result
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_disk_facts.py b/lib/ansible/modules/windows/win_disk_facts.py
deleted file mode 100644
index b203d79002..0000000000
--- a/lib/ansible/modules/windows/win_disk_facts.py
+++ /dev/null
@@ -1,891 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Marc Tschapek <marc.tschapek@itelligence.de>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_disk_facts
-version_added: '2.5'
-short_description: Show the attached disks and disk information of the target host
-description:
- - With the module you can retrieve and output detailed information about the attached disks of the target and
- its volumes and partitions if existent.
-requirements:
- - Windows 8.1 / Windows 2012 (NT 6.2)
-notes:
- - In order to understand all the returned properties and values please visit the following site and open the respective MSFT class
- U(https://msdn.microsoft.com/en-us/library/windows/desktop/hh830612.aspx)
-author:
- - Marc Tschapek (@marqelme)
-'''
-
-EXAMPLES = r'''
-- name: Get disk facts
- win_disk_facts:
-
-- name: Output first disk size
- debug:
- var: ansible_facts.disks[0].size
-
-- name: Convert first system disk into various formats
- debug:
- msg: '{{ disksize_gib }} vs {{ disksize_gib_human }}'
- vars:
- # Get first system disk
- disk: '{{ ansible_facts.disks|selectattr("system_disk")|first }}'
-
- # Show disk size in Gibibytes
- disksize_gib_human: '{{ disk.size|filesizeformat(true) }}' # returns "223.6 GiB" (human readable)
- disksize_gib: '{{ (disk.size/1024|pow(3))|round|int }} GiB' # returns "224 GiB" (value in GiB)
-
- # Show disk size in Gigabytes
- disksize_gb_human: '{{ disk.size|filesizeformat }}' # returns "240.1 GB" (human readable)
- disksize_gb: '{{ (disk.size/1000|pow(3))|round|int }} GB' # returns "240 GB" (value in GB)
-
-- name: Output second disk serial number
- debug:
- var: ansible_facts.disks[1].serial_number
-'''
-
-RETURN = r'''
-ansible_facts:
- description: Dictionary containing all the detailed information about the disks of the target.
- returned: always
- type: complex
- contains:
- ansible_disks:
- description: Detailed information about one particular disk.
- returned: if disks were found
- type: list
- contains:
- number:
- description: Disk number of the particular disk.
- returned: always
- type: int
- sample: 0
- size:
- description: Size in bytes of the particular disk.
- returned: always
- type: int
- sample: 227727638528
- bus_type:
- description: Bus type of the particular disk.
- returned: always
- type: str
- sample: "SCSI"
- friendly_name:
- description: Friendly name of the particular disk.
- returned: always
- type: str
- sample: "Red Hat VirtIO SCSI Disk Device"
- partition_style:
- description: Partition style of the particular disk.
- returned: always
- type: str
- sample: "MBR"
- partition_count:
- description: Number of partitions on the particular disk.
- returned: always
- type: int
- sample: 4
- operational_status:
- description: Operational status of the particular disk.
- returned: always
- type: str
- sample: "Online"
- sector_size:
- description: Sector size in bytes of the particular disk.
- returned: always
- type: int
- sample: 4096
- read_only:
- description: Read only status of the particular disk.
- returned: always
- type: bool
- sample: true
- bootable:
- description: Information whether the particular disk is a bootable disk.
- returned: always
- type: bool
- sample: false
- system_disk:
- description: Information whether the particular disk is a system disk.
- returned: always
- type: bool
- sample: true
- clustered:
- description: Information whether the particular disk is clustered (part of a failover cluster).
- returned: always
- type: bool
- sample: false
- manufacturer:
- description: Manufacturer of the particular disk.
- returned: always
- type: str
- sample: "Red Hat"
- model:
- description: Model specification of the particular disk.
- returned: always
- type: str
- sample: "VirtIO"
- firmware_version:
- description: Firmware version of the particular disk.
- returned: always
- type: str
- sample: "0001"
- location:
- description: Location of the particular disk on the target.
- returned: always
- type: str
- sample: "PCIROOT(0)#PCI(0400)#SCSI(P00T00L00)"
- serial_number:
- description: Serial number of the particular disk on the target.
- returned: always
- type: str
- sample: "b62beac80c3645e5877f"
- unique_id:
- description: Unique ID of the particular disk on the target.
- returned: always
- type: str
- sample: "3141463431303031"
- guid:
- description: GUID of the particular disk on the target.
- returned: if existent
- type: str
- sample: "{efa5f928-57b9-47fc-ae3e-902e85fbe77f}"
- path:
- description: Path of the particular disk on the target.
- returned: always
- type: str
- sample: "\\\\?\\scsi#disk&ven_red_hat&prod_virtio#4&23208fd0&1&000000#{<id>}"
- partitions:
- description: Detailed information about one particular partition on the specified disk.
- returned: if existent
- type: list
- contains:
- number:
- description: Number of the particular partition.
- returned: always
- type: int
- sample: 1
- size:
- description:
- - Size in bytes of the particular partition.
- returned: always
- type: int
- sample: 838860800
- type:
- description: Type of the particular partition.
- returned: always
- type: str
- sample: "IFS"
- gpt_type:
- description: gpt type of the particular partition.
- returned: if partition_style property of the particular disk has value "GPT"
- type: str
- sample: "{e3c9e316-0b5c-4db8-817d-f92df00215ae}"
- no_default_driveletter:
- description: Information whether the particular partition has a default drive letter or not.
- returned: if partition_style property of the particular disk has value "GPT"
- type: bool
- sample: true
- mbr_type:
- description: mbr type of the particular partition.
- returned: if partition_style property of the particular disk has value "MBR"
- type: int
- sample: 7
- active:
- description: Information whether the particular partition is an active partition or not.
- returned: if partition_style property of the particular disk has value "MBR"
- type: bool
- sample: true
- drive_letter:
- description: Drive letter of the particular partition.
- returned: if existent
- type: str
- sample: "C"
- transition_state:
- description: Transition state of the particular partition.
- returned: always
- type: int
- sample: 1
- offset:
- description: Offset of the particular partition.
- returned: always
- type: int
- sample: 368050176
- hidden:
- description: Information whether the particular partition is hidden or not.
- returned: always
- type: bool
- sample: true
- shadow_copy:
- description: Information whether the particular partition is a shadow copy of another partition.
- returned: always
- type: bool
- sample: false
- guid:
- description: GUID of the particular partition.
- returned: if existent
- type: str
- sample: "{302e475c-6e64-4674-a8e2-2f1c7018bf97}"
- access_paths:
- description: Access paths of the particular partition.
- returned: if existent
- type: str
- sample: "\\\\?\\Volume{85bdc4a8-f8eb-11e6-80fa-806e6f6e6963}\\"
- volumes:
- description: Detailed information about one particular volume on the specified partition.
- returned: if existent
- type: list
- contains:
- size:
- description:
- - Size in bytes of the particular volume.
- returned: always
- type: int
- sample: 838856704
- size_remaining:
- description:
- - Remaining size in bytes of the particular volume.
- returned: always
- type: int
- sample: 395620352
- type:
- description: File system type of the particular volume.
- returned: always
- type: str
- sample: "NTFS"
- label:
- description: File system label of the particular volume.
- returned: always
- type: str
- sample: "System Reserved"
- health_status:
- description: Health status of the particular volume.
- returned: always
- type: str
- sample: "Healthy"
- drive_type:
- description: Drive type of the particular volume.
- returned: always
- type: str
- sample: "Fixed"
- allocation_unit_size:
- description: Allocation unit size in bytes of the particular volume.
- returned: always
- type: int
- sample: 4096
- object_id:
- description: Object ID of the particular volume.
- returned: always
- type: str
- sample: "\\\\?\\Volume{85bdc4a9-f8eb-11e6-80fa-806e6f6e6963}\\"
- path:
- description: Path of the particular volume.
- returned: always
- type: str
- sample: "\\\\?\\Volume{85bdc4a9-f8eb-11e6-80fa-806e6f6e6963}\\"
- physical_disk:
- description: Detailed information about physical disk properties of the particular disk.
- returned: if existent
- type: complex
- contains:
- media_type:
- description: Media type of the particular physical disk.
- returned: always
- type: str
- sample: "UnSpecified"
- size:
- description:
- - Size in bytes of the particular physical disk.
- returned: always
- type: int
- sample: 240057409536
- allocated_size:
- description:
- - Allocated size in bytes of the particular physical disk.
- returned: always
- type: int
- sample: 240057409536
- device_id:
- description: Device ID of the particular physical disk.
- returned: always
- type: str
- sample: "0"
- friendly_name:
- description: Friendly name of the particular physical disk.
- returned: always
- type: str
- sample: "PhysicalDisk0"
- operational_status:
- description: Operational status of the particular physical disk.
- returned: always
- type: str
- sample: "OK"
- health_status:
- description: Health status of the particular physical disk.
- returned: always
- type: str
- sample: "Healthy"
- bus_type:
- description: Bus type of the particular physical disk.
- returned: always
- type: str
- sample: "SCSI"
- usage_type:
- description: Usage type of the particular physical disk.
- returned: always
- type: str
- sample: "Auto-Select"
- supported_usages:
- description: Supported usage types of the particular physical disk.
- returned: always
- type: complex
- contains:
- Count:
- description: Count of supported usage types.
- returned: always
- type: int
- sample: 5
- value:
- description: List of supported usage types.
- returned: always
- type: str
- sample: "Auto-Select, Hot Spare"
- spindle_speed:
- description: Spindle speed in rpm of the particular physical disk.
- returned: always
- type: int
- sample: 4294967295
- physical_location:
- description: Physical location of the particular physical disk.
- returned: always
- type: str
- sample: "Integrated : Adapter 3 : Port 0 : Target 0 : LUN 0"
- manufacturer:
- description: Manufacturer of the particular physical disk.
- returned: always
- type: str
- sample: "SUSE"
- model:
- description: Model of the particular physical disk.
- returned: always
- type: str
- sample: "Xen Block"
- can_pool:
- description: Information whether the particular physical disk can be added to a storage pool.
- returned: always
- type: bool
- sample: false
- cannot_pool_reason:
- description: Information why the particular physical disk can not be added to a storage pool.
- returned: if can_pool property has value false
- type: str
- sample: "Insufficient Capacity"
- indication_enabled:
- description: Information whether indication is enabled for the particular physical disk.
- returned: always
- type: bool
- sample: true
- partial:
- description: Information whether the particular physical disk is partial.
- returned: always
- type: bool
- sample: false
- serial_number:
- description: Serial number of the particular physical disk.
- returned: always
- type: str
- sample: "b62beac80c3645e5877f"
- object_id:
- description: Object ID of the particular physical disk.
- returned: always
- type: str
- sample: '{1}\\\\HOST\\root/Microsoft/Windows/Storage/Providers_v2\\SPACES_PhysicalDisk.ObjectId=\"{<object_id>}:PD:{<pd>}\"'
- unique_id:
- description: Unique ID of the particular physical disk.
- returned: always
- type: str
- sample: "3141463431303031"
- virtual_disk:
- description: Detailed information about virtual disk properties of the particular disk.
- returned: if existent
- type: complex
- contains:
- size:
- description:
- - Size in bytes of the particular virtual disk.
- returned: always
- type: int
- sample: 240057409536
- allocated_size:
- description:
- - Allocated size in bytes of the particular virtual disk.
- returned: always
- type: int
- sample: 240057409536
- footprint_on_pool:
- description:
- - Footprint on pool in bytes of the particular virtual disk.
- returned: always
- type: int
- sample: 240057409536
- name:
- description: Name of the particular virtual disk.
- returned: always
- type: str
- sample: "vDisk1"
- friendly_name:
- description: Friendly name of the particular virtual disk.
- returned: always
- type: str
- sample: "Prod2 Virtual Disk"
- operational_status:
- description: Operational status of the particular virtual disk.
- returned: always
- type: str
- sample: "OK"
- health_status:
- description: Health status of the particular virtual disk.
- returned: always
- type: str
- sample: "Healthy"
- provisioning_type:
- description: Provisioning type of the particular virtual disk.
- returned: always
- type: str
- sample: "Thin"
- allocation_unit_size:
- description: Allocation unit size in bytes of the particular virtual disk.
- returned: always
- type: int
- sample: 4096
- media_type:
- description: Media type of the particular virtual disk.
- returned: always
- type: str
- sample: "Unspecified"
- parity_layout:
- description: Parity layout of the particular virtual disk.
- returned: if existent
- type: int
- sample: 1
- access:
- description: Access of the particular virtual disk.
- returned: always
- type: str
- sample: "Read/Write"
- detached_reason:
- description: Detached reason of the particular virtual disk.
- returned: always
- type: str
- sample: "None"
- write_cache_size:
- description: Write cache size in byte of the particular virtual disk.
- returned: always
- type: int
- sample: 100
- fault_domain_awareness:
- description: Fault domain awareness of the particular virtual disk.
- returned: always
- type: str
- sample: "PhysicalDisk"
- inter_leave:
- description:
- - Inter leave in bytes of the particular virtual disk.
- returned: always
- type: int
- sample: 102400
- deduplication_enabled:
- description: Information whether deduplication is enabled for the particular virtual disk.
- returned: always
- type: bool
- sample: true
- enclosure_aware:
- description: Information whether the particular virtual disk is enclosure aware.
- returned: always
- type: bool
- sample: false
- manual_attach:
- description: Information whether the particular virtual disk is manual attached.
- returned: always
- type: bool
- sample: true
- snapshot:
- description: Information whether the particular virtual disk is a snapshot.
- returned: always
- type: bool
- sample: false
- tiered:
- description: Information whether the particular virtual disk is tiered.
- returned: always
- type: bool
- sample: true
- physical_sector_size:
- description: Physical sector size in bytes of the particular virtual disk.
- returned: always
- type: int
- sample: 4096
- logical_sector_size:
- description: Logical sector size in byte of the particular virtual disk.
- returned: always
- type: int
- sample: 512
- available_copies:
- description: Number of the available copies of the particular virtual disk.
- returned: if existent
- type: int
- sample: 1
- columns:
- description: Number of the columns of the particular virtual disk.
- returned: always
- type: int
- sample: 2
- groups:
- description: Number of the groups of the particular virtual disk.
- returned: always
- type: int
- sample: 1
- physical_disk_redundancy:
- description: Type of the physical disk redundancy of the particular virtual disk.
- returned: always
- type: int
- sample: 1
- read_cache_size:
- description: Read cache size in byte of the particular virtual disk.
- returned: always
- type: int
- sample: 0
- request_no_spof:
- description: Information whether the particular virtual disk requests no single point of failure.
- returned: always
- type: bool
- sample: true
- resiliency_setting_name:
- description: Type of the physical disk redundancy of the particular virtual disk.
- returned: always
- type: int
- sample: 1
- object_id:
- description: Object ID of the particular virtual disk.
- returned: always
- type: str
- sample: '{1}\\\\HOST\\root/Microsoft/Windows/Storage/Providers_v2\\SPACES_VirtualDisk.ObjectId=\"{<object_id>}:VD:{<vd>}\"'
- unique_id:
- description: Unique ID of the particular virtual disk.
- returned: always
- type: str
- sample: "260542E4C6B01D47A8FA7630FD90FFDE"
- unique_id_format:
- description: Unique ID format of the particular virtual disk.
- returned: always
- type: str
- sample: "Vendor Specific"
- win32_disk_drive:
- description: Representation of the Win32_DiskDrive class.
- returned: if existent
- type: complex
- contains:
- availability:
- description: Availability and status of the device.
- returned: always
- type: int
- bytes_per_sector:
- description: Number of bytes in each sector for the physical disk drive.
- returned: always
- type: int
- sample: 512
- capabilities:
- description:
- - Array of capabilities of the media access device.
- - For example, the device may support random access (3), removable media (7), and automatic cleaning (9).
- returned: always
- type: list
- sample:
- - 3
- - 4
- capability_descriptions:
- description:
- - List of more detailed explanations for any of the access device features indicated in the Capabilities array.
- - Note, each entry of this array is related to the entry in the Capabilities array that is located at the same index.
- returned: always
- type: list
- sample:
- - Random Access
- - Supports Writing
- caption:
- description: Short description of the object.
- returned: always
- type: str
- sample: VMware Virtual disk SCSI Disk Device
- compression_method:
- description: Algorithm or tool used by the device to support compression.
- returned: always
- type: str
- sample: Compressed
- config_manager_error_code:
- description: Windows Configuration Manager error code.
- returned: always
- type: int
- sample: 0
- config_manager_user_config:
- description: If True, the device is using a user-defined configuration.
- returned: always
- type: bool
- sample: true
- creation_class_name:
- description:
- - Name of the first concrete class to appear in the inheritance chain used in the creation of an instance.
- - When used with the other key properties of the class, the property allows all instances of this class
- - and its subclasses to be uniquely identified.
- returned: always
- type: str
- sample: Win32_DiskDrive
- default_block_size:
- description: Default block size, in bytes, for this device.
- returned: always
- type: int
- sample: 512
- description:
- description: Description of the object.
- returned: always
- type: str
- sample: Disk drive
- device_id:
- description: Unique identifier of the disk drive with other devices on the system.
- returned: always
- type: str
- sample: "\\\\.\\PHYSICALDRIVE0"
- error_cleared:
- description: If True, the error reported in LastErrorCode is now cleared.
- returned: always
- type: bool
- sample: true
- error_description:
- description:
- - More information about the error recorded in LastErrorCode,
- - and information on any corrective actions that may be taken.
- returned: always
- type: str
- error_methodology:
- description: Type of error detection and correction supported by this device.
- returned: always
- type: str
- firmware_revision:
- description: Revision for the disk drive firmware that is assigned by the manufacturer.
- returned: always
- type: str
- sample: 1.0
- index:
- description:
- - Physical drive number of the given drive.
- - This property is filled by the STORAGE_DEVICE_NUMBER structure returned from the IOCTL_STORAGE_GET_DEVICE_NUMBER control code
- - A value of 0xffffffff indicates that the given drive does not map to a physical drive.
- returned: always
- type: int
- sample: 0
- install_date:
- description: Date and time the object was installed. This property does not need a value to indicate that the object is installed.
- returned: always
- type: str
- interface_type:
- description: Interface type of physical disk drive.
- returned: always
- type: str
- sample: SCSI
- last_error_code:
- description: Last error code reported by the logical device.
- returned: always
- type: int
- manufacturer:
- description: Name of the disk drive manufacturer.
- returned: always
- type: str
- sample: Seagate
- max_block_size:
- description: Maximum block size, in bytes, for media accessed by this device.
- returned: always
- type: int
- max_media_size:
- description: Maximum media size, in kilobytes, of media supported by this device.
- returned: always
- type: int
- media_loaded:
- description:
- - If True, the media for a disk drive is loaded, which means that the device has a readable file system and is accessible.
- - For fixed disk drives, this property will always be TRUE.
- returned: always
- type: bool
- sample: true
- media_type:
- description: Type of media used or accessed by this device.
- returned: always
- type: str
- sample: Fixed hard disk media
- min_block_size:
- description: Minimum block size, in bytes, for media accessed by this device.
- returned: always
- type: int
- model:
- description: Manufacturer's model number of the disk drive.
- returned: always
- type: str
- sample: ST32171W
- name:
- description: Label by which the object is known. When subclassed, the property can be overridden to be a key property.
- returned: always
- type: str
- sample: \\\\.\\PHYSICALDRIVE0
- needs_cleaning:
- description:
- - If True, the media access device needs cleaning.
- - Whether manual or automatic cleaning is possible is indicated in the Capabilities property.
- returned: always
- type: bool
- number_of_media_supported:
- description:
- - Maximum number of media which can be supported or inserted
- - (when the media access device supports multiple individual media).
- returned: always
- type: int
- partitions:
- description: Number of partitions on this physical disk drive that are recognized by the operating system.
- returned: always
- type: int
- sample: 3
- pnp_device_id:
- description: Windows Plug and Play device identifier of the logical device.
- returned: always
- type: str
- sample: "SCSI\\DISK&VEN_VMWARE&PROD_VIRTUAL_DISK\\5&1982005&0&000000"
- power_management_capabilities:
- description: Array of the specific power-related capabilities of a logical device.
- returned: always
- type: list
- power_management_supported:
- description:
- - If True, the device can be power-managed (can be put into suspend mode, and so on).
- - The property does not indicate that power management features are currently enabled,
- - only that the logical device is capable of power management.
- returned: always
- type: bool
- scsi_bus:
- description: SCSI bus number of the disk drive.
- returned: always
- type: int
- sample: 0
- scsi_logical_unit:
- description: SCSI logical unit number (LUN) of the disk drive.
- returned: always
- type: int
- sample: 0
- scsi_port:
- description: SCSI port number of the disk drive.
- returned: always
- type: int
- sample: 0
- scsi_target_id:
- description: SCSI identifier number of the disk drive.
- returned: always
- type: int
- sample: 0
- sectors_per_track:
- description: Number of sectors in each track for this physical disk drive.
- returned: always
- type: int
- sample: 63
- serial_number:
- description: Number allocated by the manufacturer to identify the physical media.
- returned: always
- type: str
- sample: 6000c298f34101b38cb2b2508926b9de
- signature:
- description: Disk identification. This property can be used to identify a shared resource.
- returned: always
- type: int
- size:
- description:
- - Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder,
- - sectors in each track, and bytes in each sector.
- returned: always
- type: int
- sample: 53686402560
- status:
- description:
- - Current status of the object. Various operational and nonoperational statuses can be defined.
- - 'Operational statuses include: "OK", "Degraded", and "Pred Fail"'
- - (an element, such as a SMART-enabled hard disk drive, may be functioning properly but predicting a failure in the near future).
- - 'Nonoperational statuses include: "Error", "Starting", "Stopping", and "Service".'
- - '"Service", could apply during mirror-resilvering of a disk, reload of a user permissions list, or other administrative work.'
- - Not all such work is online, yet the managed element is neither "OK" nor in one of the other states.
- returned: always
- type: str
- sample: OK
- status_info:
- description:
- - State of the logical device. If this property does not apply to the logical device, the value 5 (Not Applicable) should be used.
- returned: always
- type: int
- system_creation_class_name:
- description: Value of the scoping computer's CreationClassName property.
- returned: always
- type: str
- sample: Win32_ComputerSystem
- system_name:
- description: Name of the scoping system.
- returned: always
- type: str
- sample: WILMAR-TEST-123
- total_cylinders:
- description:
- - Total number of cylinders on the physical disk drive.
- - 'Note: the value for this property is obtained through extended functions of BIOS interrupt 13h.'
- - The value may be inaccurate if the drive uses a translation scheme to support high-capacity disk sizes.
- - Consult the manufacturer for accurate drive specifications.
- returned: always
- type: int
- sample: 6527
- total_heads:
- description:
- - Total number of heads on the disk drive.
- - 'Note: the value for this property is obtained through extended functions of BIOS interrupt 13h.'
- - The value may be inaccurate if the drive uses a translation scheme to support high-capacity disk sizes.
- - Consult the manufacturer for accurate drive specifications.
- returned: always
- type: int
- sample: 255
- total_sectors:
- description:
- - Total number of sectors on the physical disk drive.
- - 'Note: the value for this property is obtained through extended functions of BIOS interrupt 13h.'
- - The value may be inaccurate if the drive uses a translation scheme to support high-capacity disk sizes.
- - Consult the manufacturer for accurate drive specifications.
- returned: always
- type: int
- sample: 104856255
- total_tracks:
- description:
- - Total number of tracks on the physical disk drive.
- - 'Note: the value for this property is obtained through extended functions of BIOS interrupt 13h.'
- - The value may be inaccurate if the drive uses a translation scheme to support high-capacity disk sizes.
- - Consult the manufacturer for accurate drive specifications.
- returned: always
- type: int
- sample: 1664385
- tracks_per_cylinder:
- description:
- - Number of tracks in each cylinder on the physical disk drive.
- - 'Note: the value for this property is obtained through extended functions of BIOS interrupt 13h.'
- - The value may be inaccurate if the drive uses a translation scheme to support high-capacity disk sizes.
- - Consult the manufacturer for accurate drive specifications.
- returned: always
- type: int
- sample: 255
-'''
diff --git a/lib/ansible/modules/windows/win_disk_image.ps1 b/lib/ansible/modules/windows/win_disk_image.ps1
deleted file mode 100644
index a5627fde53..0000000000
--- a/lib/ansible/modules/windows/win_disk_image.ps1
+++ /dev/null
@@ -1,78 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Red Hat, Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-Set-StrictMode -Version 2
-
-If(-not (Get-Command Get-DiskImage -ErrorAction SilentlyContinue)) {
- Fail-Json -message "win_disk_image requires Windows 8+ or Windows Server 2012+"
-}
-
-$parsed_args = Parse-Args $args -supports_check_mode $true
-
-$result = @{changed=$false}
-
-$image_path = Get-AnsibleParam $parsed_args "image_path" -failifempty $result
-$state = Get-AnsibleParam $parsed_args "state" -default "present" -validateset "present","absent"
-$check_mode = Get-AnsibleParam $parsed_args "_ansible_check_mode" -default $false
-
-$di = Get-DiskImage $image_path
-
-If($state -eq "present") {
- If(-not $di.Attached) {
- $result.changed = $true
-
- If(-not $check_mode) {
- $di = Mount-DiskImage $image_path -PassThru
-
- # the actual mount is async, so the CIMInstance result may not immediately contain the data we need
- $retry_count = 0
- While(-not $di.Attached -and $retry_count -lt 5) {
- Start-Sleep -Seconds 1 > $null
- $di = $di | Get-DiskImage
- $retry_count++
- }
-
- If(-not $di.Attached) {
- Fail-Json $result -message "Timed out waiting for disk to attach"
- }
- }
- }
-
- # FUTURE: detect/handle "ejected" ISOs
- # FUTURE: support explicit drive letter and NTFS in-volume mountpoints.
- # VHDs don't always auto-assign, and other system settings can prevent automatic assignment
-
- If($di.Attached) { # only try to get the mount_path if the disk is attached (
- If($di.StorageType -eq 1) { # ISO, we can get the mountpoint directly from Get-Volume
- $drive_letters = ($di | Get-Volume).DriveLetter
- }
- ElseIf($di.StorageType -in @(2,3)) { # VHD/VHDX, need Get-Disk + Get-Partition to discover mountpoint
- $drive_letters = ($di | Get-Disk | Get-Partition).DriveLetter
- }
- # remove any null entries (no drive letter)
- $drive_letters = $drive_letters | Where-Object { $_ }
-
- If(-not $drive_letters) {
- Fail-Json -message "Unable to retrieve drive letter from mounted image"
- }
-
- # mount_path is deprecated and will be removed in 2.11, use mount_paths which contains all the partitions instead
- $result.mount_path = $drive_letters[0] + ":\"
- $result.mount_paths = @($drive_letters | ForEach-Object { "$($_):\" })
- }
-}
-ElseIf($state -eq "absent") {
- If($di.Attached) {
- $result.changed = $true
- If(-not $check_mode) {
- Dismount-DiskImage $image_path > $null
- }
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_disk_image.py b/lib/ansible/modules/windows/win_disk_image.py
deleted file mode 100644
index 9a83e49693..0000000000
--- a/lib/ansible/modules/windows/win_disk_image.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Red Hat, Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'core'}
-
-DOCUMENTATION = r'''
-module: win_disk_image
-short_description: Manage ISO/VHD/VHDX mounts on Windows hosts
-version_added: '2.3'
-description:
- - Manages mount behavior for a specified ISO, VHD, or VHDX image on a Windows host. When C(state) is C(present),
- the image will be mounted under a system-assigned drive letter, which will be returned in the C(mount_path) value
- of the module result.
- - Requires Windows 8+ or Windows Server 2012+.
-options:
- image_path:
- description:
- - Path to an ISO, VHD, or VHDX image on the target Windows host (the file cannot reside on a network share)
- type: str
- required: yes
- state:
- description:
- - Whether the image should be present as a drive-letter mount or not.
- type: str
- choices: [ absent, present ]
- default: present
-author:
- - Matt Davis (@nitzmahone)
-'''
-
-EXAMPLES = r'''
-# Run installer from mounted ISO, then unmount
-- name: Ensure an ISO is mounted
- win_disk_image:
- image_path: C:\install.iso
- state: present
- register: disk_image_out
-
-- name: Run installer from mounted ISO
- win_package:
- path: '{{ disk_image_out.mount_paths[0] }}setup\setup.exe'
- product_id: 35a4e767-0161-46b0-979f-e61f282fee21
- state: present
-
-- name: Unmount ISO
- win_disk_image:
- image_path: C:\install.iso
- state: absent
-'''
-
-RETURN = r'''
-mount_path:
- description: Filesystem path where the target image is mounted, this has been deprecated in favour of C(mount_paths).
- returned: when C(state) is C(present)
- type: str
- sample: F:\
-mount_paths:
- description: A list of filesystem paths mounted from the target image.
- returned: when C(state) is C(present)
- type: list
- sample: [ 'E:\', 'F:\' ]
-'''
diff --git a/lib/ansible/modules/windows/win_dns_record.ps1 b/lib/ansible/modules/windows/win_dns_record.ps1
deleted file mode 100644
index e3937dbad8..0000000000
--- a/lib/ansible/modules/windows/win_dns_record.ps1
+++ /dev/null
@@ -1,149 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Hitachi ID Systems, Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-$spec = @{
- options = @{
- name = @{ type = "str"; required = $true }
- state = @{ type = "str"; choices = "absent", "present"; default = "present" }
- ttl = @{ type = "int"; default = "3600" }
- type = @{ type = "str"; choices = "A","AAAA","CNAME","PTR"; required = $true }
- value = @{ type = "list"; elements = "str"; default = @() ; aliases=@( 'values' )}
- zone = @{ type = "str"; required = $true }
- computer_name = @{ type = "str" }
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$name = $module.Params.name
-$state = $module.Params.state
-$ttl = $module.Params.ttl
-$type = $module.Params.type
-$values = $module.Params.value
-$zone = $module.Params.zone
-$dns_computer_name = $module.Params.computer_name
-
-
-$extra_args = @{}
-if ($null -ne $dns_computer_name) {
- $extra_args.ComputerName = $dns_computer_name
-}
-
-if ($state -eq 'present') {
- if ($values.Count -eq 0) {
- $module.FailJson("Parameter 'values' must be non-empty when state='present'")
- }
-} else {
- if ($values.Count -ne 0) {
- $module.FailJson("Parameter 'values' must be undefined or empty when state='absent'")
- }
-}
-
-
-# TODO: add warning for forest minTTL override -- see https://docs.microsoft.com/en-us/windows/desktop/ad/configuration-of-ttl-limits
-if ($ttl -lt 1 -or $ttl -gt 31557600) {
- $module.FailJson("Parameter 'ttl' must be between 1 and 31557600")
-}
-$ttl = New-TimeSpan -Seconds $ttl
-
-
-if (($type -eq 'CNAME' -or $type -eq 'PTR') -and $null -ne $values -and $values.Count -gt 0 -and $zone[-1] -ne '.') {
- # CNAMEs and PTRs should be '.'-terminated, or record matching will fail
- $values = $values | ForEach-Object {
- if ($_ -Like "*.") { $_ } else { "$_." }
- }
-}
-
-
-$record_argument_name = @{
- A = "IPv4Address";
- AAAA = "IPv6Address";
- CNAME = "HostNameAlias";
- # MX = "MailExchange";
- # NS = "NameServer";
- PTR = "PtrDomainName";
- # TXT = "DescriptiveText"
-}[$type]
-
-
-$changes = @{
- before = "";
- after = ""
-}
-
-
-$records = Get-DnsServerResourceRecord -ZoneName $zone -Name $name -RRType $type -Node -ErrorAction:Ignore @extra_args | Sort-Object
-if ($null -ne $records) {
- # We use [Hashtable]$required_values below as a set rather than a map.
- # It provides quick lookup to test existing DNS record against. By removing
- # items as each is processed, whatever remains at the end is missing
- # content (that needs to be added).
- $required_values = @{}
- foreach ($value in $values) {
- $required_values[$value.ToString()] = $null
- }
-
- foreach ($record in $records) {
- $record_value = $record.RecordData.$record_argument_name.ToString()
-
- if ($required_values.ContainsKey($record_value)) {
- # This record matches one of the values; but does it match the TTL?
- if ($record.TimeToLive -ne $ttl) {
- $new_record = $record.Clone()
- $new_record.TimeToLive = $ttl
- Set-DnsServerResourceRecord -ZoneName $zone -OldInputObject $record -NewInputObject $new_record -WhatIf:$module.CheckMode @extra_args
-
- $changes.before += "[$zone] $($record.HostName) $($record.TimeToLive.TotalSeconds) IN $type $record_value`n"
- $changes.after += "[$zone] $($record.HostName) $($ttl.TotalSeconds) IN $type $record_value`n"
- $module.Result.changed = $true
- }
-
- # Cross this one off the list, so we don't try adding it later
- $required_values.Remove($record_value)
- } else {
- # This record doesn't match any of the values, and must be removed
- $record | Remove-DnsServerResourceRecord -ZoneName $zone -Force -WhatIf:$module.CheckMode @extra_args
-
- $changes.before += "[$zone] $($record.HostName) $($record.TimeToLive.TotalSeconds) IN $type $record_value`n"
- $module.Result.changed = $true
- }
- }
-
- # Whatever is left in $required_values needs to be added
- $values = $required_values.Keys
-}
-
-
-if ($null -ne $values -and $values.Count -gt 0) {
- foreach ($value in $values) {
- $splat_args = @{ $type = $true; $record_argument_name = $value }
- $module.Result.debug_splat_args = $splat_args
- try {
- Add-DnsServerResourceRecord -ZoneName $zone -Name $name -AllowUpdateAny -TimeToLive $ttl @splat_args -WhatIf:$module.CheckMode @extra_args
- } catch {
- $module.FailJson("Error adding DNS $type resource $name in zone $zone with value $value", $_)
- }
- $changes.after += "[$zone] $name $($ttl.TotalSeconds) IN $type $value`n"
- }
-
- $module.Result.changed = $true
-}
-
-if ($module.CheckMode) {
- # Simulated changes
- $module.Diff.before = $changes.before
- $module.Diff.after = $changes.after
-} else {
- # Real changes
- $records_end = Get-DnsServerResourceRecord -ZoneName $zone -Name $name -RRType $type -Node -ErrorAction:Ignore @extra_args | Sort-Object
-
- $module.Diff.before = @($records | ForEach-Object { "[$zone] $($_.HostName) $($_.TimeToLive.TotalSeconds) IN $type $($_.RecordData.$record_argument_name.ToString())`n" }) -join ''
- $module.Diff.after = @($records_end | ForEach-Object { "[$zone] $($_.HostName) $($_.TimeToLive.TotalSeconds) IN $type $($_.RecordData.$record_argument_name.ToString())`n" }) -join ''
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_dns_record.py b/lib/ansible/modules/windows/win_dns_record.py
deleted file mode 100644
index 0d5e631072..0000000000
--- a/lib/ansible/modules/windows/win_dns_record.py
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2019, Hitachi ID Systems, Inc.
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# This is a windows documentation stub. The actual code lives in the .ps1
-# file of the same name.
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_dns_record
-version_added: "2.8"
-short_description: Manage Windows Server DNS records
-description:
-- Manage DNS records within an existing Windows Server DNS zone.
-author: John Nelson (@johnboy2)
-requirements:
- - This module requires Windows 8, Server 2012, or newer.
-options:
- name:
- description:
- - The name of the record.
- required: yes
- type: str
- state:
- description:
- - Whether the record should exist or not.
- choices: [ absent, present ]
- default: present
- type: str
- ttl:
- description:
- - The "time to live" of the record, in seconds.
- - Ignored when C(state=absent).
- - Valid range is 1 - 31557600.
- - Note that an Active Directory forest can specify a minimum TTL, and will
- dynamically "round up" other values to that minimum.
- default: 3600
- type: int
- type:
- description:
- - The type of DNS record to manage.
- choices: [ A, AAAA, CNAME, PTR ]
- required: yes
- type: str
- value:
- description:
- - The value(s) to specify. Required when C(state=present).
- - When C(type=PTR) only the partial part of the IP should be given.
- aliases: [ values ]
- type: list
- zone:
- description:
- - The name of the zone to manage (eg C(example.com)).
- - The zone must already exist.
- required: yes
- type: str
- computer_name:
- description:
- - Specifies a DNS server.
- - You can specify an IP address or any value that resolves to an IP
- address, such as a fully qualified domain name (FQDN), host name, or
- NETBIOS name.
- type: str
-'''
-
-EXAMPLES = r'''
-# Demonstrate creating a matching A and PTR record.
-
-- name: Create database server record
- win_dns_record:
- name: "cgyl1404p.amer.example.com"
- type: "A"
- value: "10.1.1.1"
- zone: "amer.example.com"
-
-- name: Create matching PTR record
- win_dns_record:
- name: "1.1.1"
- type: "PTR"
- value: "db1"
- zone: "10.in-addr.arpa"
-
-# Demonstrate replacing an A record with a CNAME
-
-- name: Remove static record
- win_dns_record:
- name: "db1"
- type: "A"
- state: absent
- zone: "amer.example.com"
-
-- name: Create database server alias
- win_dns_record:
- name: "db1"
- type: "CNAME"
- value: "cgyl1404p.amer.example.com"
- zone: "amer.example.com"
-
-# Demonstrate creating multiple A records for the same name
-
-- name: Create multiple A record values for www
- win_dns_record:
- name: "www"
- type: "A"
- values:
- - 10.0.42.5
- - 10.0.42.6
- - 10.0.42.7
- zone: "example.com"
-
-# Demonstrates a partial update (replace some existing values with new ones)
-# for a pre-existing name
-
-- name: Update www host with new addresses
- win_dns_record:
- name: "www"
- type: "A"
- values:
- - 10.0.42.5 # this old value was kept (others removed)
- - 10.0.42.12 # this new value was added
- zone: "example.com"
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_domain_computer.ps1 b/lib/ansible/modules/windows/win_domain_computer.ps1
deleted file mode 100644
index 3da4a6f785..0000000000
--- a/lib/ansible/modules/windows/win_domain_computer.ps1
+++ /dev/null
@@ -1,208 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, AMTEGA - Xunta de Galicia
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-
-# ------------------------------------------------------------------------------
-$ErrorActionPreference = "Stop"
-
-# Preparing result
-$result = @{}
-$result.changed = $false
-
-# Parameter ingestion
-$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
-
-$name = Get-AnsibleParam -obj $params -name "name" -failifempty $true -resultobj $result
-$sam_account_name = Get-AnsibleParam -obj $params -name "sam_account_name" -default "$name$"
-If (-not $sam_account_name.EndsWith("$")) {
- Fail-Json -obj $result -message "sam_account_name must end in $"
-}
-$enabled = Get-AnsibleParam -obj $params -name "enabled" -type "bool" -default $true
-$description = Get-AnsibleParam -obj $params -name "description" -default $null
-$domain_username = Get-AnsibleParam -obj $params -name "domain_username" -type "str"
-$domain_password = Get-AnsibleParam -obj $params -name "domain_password" -type "str" -failifempty ($null -ne $domain_username)
-$domain_server = Get-AnsibleParam -obj $params -name "domain_server" -type "str"
-$state = Get-AnsibleParam -obj $params -name "state" -ValidateSet "present","absent" -default "present"
-
-$extra_args = @{}
-if ($null -ne $domain_username) {
- $domain_password = ConvertTo-SecureString $domain_password -AsPlainText -Force
- $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domain_username, $domain_password
- $extra_args.Credential = $credential
-}
-if ($null -ne $domain_server) {
- $extra_args.Server = $domain_server
-}
-
-If ($state -eq "present") {
- $dns_hostname = Get-AnsibleParam -obj $params -name "dns_hostname" -failifempty $true -resultobj $result
- $ou = Get-AnsibleParam -obj $params -name "ou" -failifempty $true -resultobj $result
- $distinguished_name = "CN=$name,$ou"
-
- $desired_state = [ordered]@{
- name = $name
- sam_account_name = $sam_account_name
- dns_hostname = $dns_hostname
- ou = $ou
- distinguished_name = $distinguished_name
- description = $description
- enabled = $enabled
- state = $state
- }
-} Else {
- $desired_state = [ordered]@{
- name = $name
- sam_account_name = $sam_account_name
- state = $state
- }
-}
-
-# ------------------------------------------------------------------------------
-Function Get-InitialState($desired_state) {
- # Test computer exists
- $computer = Try {
- Get-ADComputer `
- -Identity $desired_state.sam_account_name `
- -Properties DistinguishedName,DNSHostName,Enabled,Name,SamAccountName,Description,ObjectClass `
- @extra_args
- } Catch { $null }
- If ($computer) {
- $initial_state = [ordered]@{
- name = $computer.Name
- sam_account_name = $computer.SamAccountName
- dns_hostname = $computer.DNSHostName
- # Get OU from regexp that removes all characters to the first ","
- ou = $computer.DistinguishedName -creplace "^[^,]*,",""
- distinguished_name = $computer.DistinguishedName
- description = $computer.Description
- enabled = $computer.Enabled
- state = "present"
- }
- } Else {
- $initial_state = [ordered]@{
- name = $desired_state.name
- sam_account_name = $desired_state.sam_account_name
- state = "absent"
- }
- }
-
- return $initial_state
-}
-
-# ------------------------------------------------------------------------------
-Function Set-ConstructedState($initial_state, $desired_state) {
- Try {
- Set-ADComputer `
- -Identity $desired_state.name `
- -SamAccountName $desired_state.name `
- -DNSHostName $desired_state.dns_hostname `
- -Enabled $desired_state.enabled `
- -Description $desired_state.description `
- -WhatIf:$check_mode `
- @extra_args
- } Catch {
- Fail-Json -obj $result -message "Failed to set the AD object $($desired_state.name): $($_.Exception.Message)"
- }
-
- If ($initial_state.distinguished_name -cne $desired_state.distinguished_name) {
- # Move computer to OU
- Try {
- Get-ADComputer -Identity $desired_state.sam_account_name @extra_args |
- Move-ADObject `
- -TargetPath $desired_state.ou `
- -Confirm:$False `
- -WhatIf:$check_mode `
- @extra_args
- } Catch {
- Fail-Json -obj $result -message "Failed to move the AD object $($initial_state.distinguished_name) to $($desired_state.distinguished_name): $($_.Exception.Message)"
- }
- }
- $result.changed = $true
-}
-
-# ------------------------------------------------------------------------------
-Function Add-ConstructedState($desired_state) {
- Try {
- New-ADComputer `
- -Name $desired_state.name `
- -SamAccountName $desired_state.sam_account_name `
- -DNSHostName $desired_state.dns_hostname `
- -Path $desired_state.ou `
- -Enabled $desired_state.enabled `
- -Description $desired_state.description `
- -WhatIf:$check_mode `
- @extra_args
- } Catch {
- Fail-Json -obj $result -message "Failed to create the AD object $($desired_state.name): $($_.Exception.Message)"
- }
-
- $result.changed = $true
-}
-
-# ------------------------------------------------------------------------------
-Function Remove-ConstructedState($initial_state) {
- Try {
- Get-ADComputer -Identity $initial_state.sam_account_name @extra_args |
- Remove-ADObject `
- -Recursive `
- -Confirm:$False `
- -WhatIf:$check_mode `
- @extra_args
- } Catch {
- Fail-Json -obj $result -message "Failed to remove the AD object $($desired_state.name): $($_.Exception.Message)"
- }
-
- $result.changed = $true
-}
-
-# ------------------------------------------------------------------------------
-Function are_hashtables_equal($x, $y) {
- # Compare not nested HashTables
- Foreach ($key in $x.Keys) {
- If (($y.Keys -notcontains $key) -or ($x[$key] -cne $y[$key])) {
- Return $false
- }
- }
- foreach ($key in $y.Keys) {
- if (($x.Keys -notcontains $key) -or ($x[$key] -cne $y[$key])) {
- Return $false
- }
- }
- Return $true
-}
-
-# ------------------------------------------------------------------------------
-$initial_state = Get-InitialState($desired_state)
-
-If ($desired_state.state -eq "present") {
- If ($initial_state.state -eq "present") {
- $in_desired_state = are_hashtables_equal $initial_state $desired_state
-
- If (-not $in_desired_state) {
- Set-ConstructedState $initial_state $desired_state
- }
- } Else { # $desired_state.state = "Present" & $initial_state.state = "Absent"
- Add-ConstructedState($desired_state)
- }
- } Else { # $desired_state.state = "Absent"
- If ($initial_state.state -eq "present") {
- Remove-ConstructedState($initial_state)
- }
- }
-
-If ($diff_support) {
- $diff = @{
- before = $initial_state
- after = $desired_state
- }
- $result.diff = $diff
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_domain_computer.py b/lib/ansible/modules/windows/win_domain_computer.py
deleted file mode 100644
index f95cc5cd72..0000000000
--- a/lib/ansible/modules/windows/win_domain_computer.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, AMTEGA - Xunta de Galicia
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_domain_computer
-short_description: Manage computers in Active Directory
-description:
- - Create, read, update and delete computers in Active Directory using a
- windows bridge computer to launch New-ADComputer, Get-ADComputer,
- Set-ADComputer, Remove-ADComputer and Move-ADObject powershell commands.
-version_added: '2.6'
-options:
- name:
- description:
- - Specifies the name of the object.
- - This parameter sets the Name property of the Active Directory object.
- - The LDAP display name (ldapDisplayName) of this property is name.
- type: str
- required: true
- sam_account_name:
- description:
- - Specifies the Security Account Manager (SAM) account name of the
- computer.
- - It maximum is 256 characters, 15 is advised for older
- operating systems compatibility.
- - The LDAP display name (ldapDisplayName) for this property is sAMAccountName.
- - If ommitted the value is the same as C(name).
- - Note that all computer SAMAccountNames need to end with a $.
- type: str
- enabled:
- description:
- - Specifies if an account is enabled.
- - An enabled account requires a password.
- - This parameter sets the Enabled property for an account object.
- - This parameter also sets the ADS_UF_ACCOUNTDISABLE flag of the
- Active Directory User Account Control (UAC) attribute.
- type: bool
- default: yes
- ou:
- description:
- - Specifies the X.500 path of the Organizational Unit (OU) or container
- where the new object is created. Required when I(state=present).
- type: str
- description:
- description:
- - Specifies a description of the object.
- - This parameter sets the value of the Description property for the object.
- - The LDAP display name (ldapDisplayName) for this property is description.
- type: str
- default: ''
- dns_hostname:
- description:
- - Specifies the fully qualified domain name (FQDN) of the computer.
- - This parameter sets the DNSHostName property for a computer object.
- - The LDAP display name for this property is dNSHostName.
- - Required when I(state=present).
- type: str
- domain_username:
- description:
- - The username to use when interacting with AD.
- - If this is not set then the user Ansible used to log in with will be
- used instead when using CredSSP or Kerberos with credential delegation.
- type: str
- version_added: '2.8'
- domain_password:
- description:
- - The password for I(username).
- type: str
- version_added: '2.8'
- domain_server:
- description:
- - Specifies the Active Directory Domain Services instance to connect to.
- - Can be in the form of an FQDN or NetBIOS name.
- - If not specified then the value is based on the domain of the computer
- running PowerShell.
- type: str
- version_added: '2.8'
- state:
- description:
- - Specified whether the computer should be C(present) or C(absent) in
- Active Directory.
- type: str
- choices: [ absent, present ]
- default: present
-seealso:
-- module: win_domain
-- module: win_domain_controller
-- module: win_domain_group
-- module: win_domain_membership
-- module: win_domain_user
-author:
-- Daniel Sánchez Fábregas (@Daniel-Sanchez-Fabregas)
-'''
-
-EXAMPLES = r'''
- - name: Add linux computer to Active Directory OU using a windows machine
- win_domain_computer:
- name: one_linux_server.my_org.local
- sam_account_name: linux_server$
- dns_hostname: one_linux_server.my_org.local
- ou: "OU=servers,DC=my_org,DC=local"
- description: Example of linux server
- enabled: yes
- state: present
- delegate_to: my_windows_bridge.my_org.local
-
- - name: Remove linux computer from Active Directory using a windows machine
- win_domain_computer:
- name: one_linux_server.my_org.local
- state: absent
- delegate_to: my_windows_bridge.my_org.local
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_domain_group.ps1 b/lib/ansible/modules/windows/win_domain_group.ps1
deleted file mode 100644
index b392c52c49..0000000000
--- a/lib/ansible/modules/windows/win_domain_group.ps1
+++ /dev/null
@@ -1,344 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Jordan Borean <jborean93@gmail.com>, and others
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
-
-$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
-$display_name = Get-AnsibleParam -obj $params -name "display_name" -type "str"
-$domain_username = Get-AnsibleParam -obj $params -name "domain_username" -type "str"
-$domain_password = Get-AnsibleParam -obj $params -name "domain_password" -type "str" -failifempty ($null -ne $domain_username)
-$description = Get-AnsibleParam -obj $params -name "description" -type "str"
-$category = Get-AnsibleParam -obj $params -name "category" -type "str" -validateset "distribution","security"
-$scope = Get-AnsibleParam -obj $params -name "scope" -type "str" -validateset "domainlocal","global","universal"
-$managed_by = Get-AnsibleParam -obj $params -name "managed_by" -type "str"
-$attributes = Get-AnsibleParam -obj $params -name "attributes"
-$organizational_unit = Get-AnsibleParam -obj $params -name "organizational_unit" -type "str" -aliases "ou","path"
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent"
-$protect = Get-AnsibleParam -obj $params -name "protect" -type "bool"
-$ignore_protection = Get-AnsibleParam -obj $params -name "ignore_protection" -type "bool" -default $false
-$domain_server = Get-AnsibleParam -obj $params -name "domain_server" -type "str"
-
-$result = @{
- changed = $false
- created = $false
-}
-
-if ($diff_mode) {
- $result.diff = @{}
-}
-
-if (-not (Get-Module -Name ActiveDirectory -ListAvailable)) {
- Fail-Json $result "win_domain_group requires the ActiveDirectory PS module to be installed"
-}
-Import-Module ActiveDirectory
-
-$extra_args = @{}
-if ($null -ne $domain_username) {
- $domain_password = ConvertTo-SecureString $domain_password -AsPlainText -Force
- $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domain_username, $domain_password
- $extra_args.Credential = $credential
-}
-if ($null -ne $domain_server) {
- $extra_args.Server = $domain_server
-}
-
-try {
- $group = Get-ADGroup -Identity $name -Properties * @extra_args
-} catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
- $group = $null
-} catch {
- Fail-Json $result "failed to retrieve initial details for group $($name): $($_.Exception.Message)"
-}
-if ($state -eq "absent") {
- if ($null -ne $group) {
- if ($group.ProtectedFromAccidentalDeletion -eq $true -and $ignore_protection -eq $true) {
- $group = $group | Set-ADObject -ProtectedFromAccidentalDeletion $false -WhatIf:$check_mode -PassThru @extra_args
- } elseif ($group.ProtectedFromAccidentalDeletion -eq $true -and $ignore_protection -eq $false) {
- Fail-Json $result "cannot delete group $name when ProtectedFromAccidentalDeletion is turned on, run this module with ignore_protection=true to override this"
- }
-
- try {
- $group | Remove-ADGroup -Confirm:$false -WhatIf:$check_mode @extra_args
- } catch {
- Fail-Json $result "failed to remove group $($name): $($_.Exception.Message)"
- }
-
- $result.changed = $true
- if ($diff_mode) {
- $result.diff.prepared = "-[$name]"
- }
- }
-} else {
- # validate that path is an actual path
- if ($null -ne $organizational_unit) {
- try {
- Get-ADObject -Identity $organizational_unit @extra_args | Out-Null
- } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
- Fail-Json $result "the group path $organizational_unit does not exist, please specify a valid LDAP path"
- }
- }
-
- $diff_text = $null
- if ($null -ne $group) {
- # will be overridden later if no change actually occurs
- $diff_text += "[$name]`n"
-
- # change the path of the group
- if ($null -ne $organizational_unit) {
- $group_cn = $group.CN
- $existing_path = $group.DistinguishedName -replace "^CN=$group_cn,",''
- if ($existing_path -ne $organizational_unit) {
- $protection_disabled = $false
- if ($group.ProtectedFromAccidentalDeletion -eq $true -and $ignore_protection -eq $true) {
- $group | Set-ADObject -ProtectedFromAccidentalDeletion $false -WhatIf:$check_mode -PassThru @extra_args | Out-Null
- $protection_disabled = $true
- } elseif ($group.ProtectedFromAccidentalDeletion -eq $true -and $ignore_protection -eq $false) {
- Fail-Json $result "cannot move group $name when ProtectedFromAccidentalDeletion is turned on, run this module with ignore_protection=true to override this"
- }
-
- try {
- $group = $group | Move-ADObject -Targetpath $organizational_unit -WhatIf:$check_mode -PassThru @extra_args
- } catch {
- Fail-Json $result "failed to move group from $existing_path to $($organizational_unit): $($_.Exception.Message)"
- } finally {
- if ($protection_disabled -eq $true) {
- $group | Set-ADObject -ProtectedFromAccidentalDeletion $true -WhatIf:$check_mode -PassThru @extra_args | Out-Null
- }
- }
-
- $result.changed = $true
- $diff_text += "-DistinguishedName = CN=$group_cn,$existing_path`n+DistinguishedName = CN=$group_cn,$organizational_unit`n"
-
- if ($protection_disabled -eq $true) {
- $group | Set-ADObject -ProtectedFromAccidentalDeletion $true -WhatIf:$check_mode @extra_args | Out-Null
- }
- # get the group again once we have moved it
- $group = Get-ADGroup -Identity $name -Properties * @extra_args
- }
- }
-
- # change attributes of group
- $extra_scope_change = $null
- $run_change = $false
- $set_args = $extra_args.Clone()
-
- if ($null -ne $scope) {
- if ($group.GroupScope -ne $scope) {
- # you cannot from from Global to DomainLocal and vice-versa, we
- # need to change it to Universal and then finally to the target
- # scope
- if ($group.GroupScope -eq "global" -and $scope -eq "domainlocal") {
- $set_args.GroupScope = "Universal"
- $extra_scope_change = $scope
- } elseif ($group.GroupScope -eq "domainlocal" -and $scope -eq "global") {
- $set_args.GroupScope = "Universal"
- $extra_scope_change = $scope
- } else {
- $set_args.GroupScope = $scope
- }
- $run_change = $true
- $diff_text += "-GroupScope = $($group.GroupScope)`n+GroupScope = $scope`n"
- }
- }
-
- if ($null -ne $description -and $group.Description -cne $description) {
- $set_args.Description = $description
- $run_change = $true
- $diff_text += "-Description = $($group.Description)`n+Description = $description`n"
- }
-
- if ($null -ne $display_name -and $group.DisplayName -cne $display_name) {
- $set_args.DisplayName = $display_name
- $run_change = $true
- $diff_text += "-DisplayName = $($group.DisplayName)`n+DisplayName = $display_name`n"
- }
-
- if ($null -ne $category -and $group.GroupCategory -ne $category) {
- $set_args.GroupCategory = $category
- $run_change = $true
- $diff_text += "-GroupCategory = $($group.GroupCategory)`n+GroupCategory = $category`n"
- }
-
- if ($null -ne $managed_by) {
- if ($null -eq $group.ManagedBy) {
- $set_args.ManagedBy = $managed_by
- $run_change = $true
- $diff_text += "+ManagedBy = $managed_by`n"
- } else {
- try {
- $managed_by_object = Get-ADGroup -Identity $managed_by @extra_args
- } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
- try {
- $managed_by_object = Get-ADUser -Identity $managed_by @extra_args
- } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
- Fail-Json $result "failed to find managed_by user or group $managed_by to be used for comparison"
- }
- }
-
- if ($group.ManagedBy -ne $managed_by_object.DistinguishedName) {
- $set_args.ManagedBy = $managed_by
- $run_change = $true
- $diff_text += "-ManagedBy = $($group.ManagedBy)`n+ManagedBy = $($managed_by_object.DistinguishedName)`n"
- }
- }
- }
-
- if ($null -ne $attributes) {
- $add_attributes = @{}
- $replace_attributes = @{}
- foreach ($attribute in $attributes.GetEnumerator()) {
- $attribute_name = $attribute.Name
- $attribute_value = $attribute.Value
-
- $valid_property = [bool]($group.PSobject.Properties.name -eq $attribute_name)
- if ($valid_property) {
- $existing_value = $group.$attribute_name
- if ($existing_value -cne $attribute_value) {
- $replace_attributes.$attribute_name = $attribute_value
- $diff_text += "-$attribute_name = $existing_value`n+$attribute_name = $attribute_value`n"
- }
- } else {
- $add_attributes.$attribute_name = $attribute_value
- $diff_text += "+$attribute_name = $attribute_value`n"
- }
- }
- if ($add_attributes.Count -gt 0) {
- $set_args.Add = $add_attributes
- $run_change = $true
- }
- if ($replace_attributes.Count -gt 0) {
- $set_args.Replace = $replace_attributes
- $run_change = $true
- }
- }
-
- if ($run_change) {
- try {
- $group = $group | Set-ADGroup -WhatIf:$check_mode -PassThru @set_args
- } catch {
- Fail-Json $result "failed to change group $($name): $($_.Exception.Message)"
- }
- $result.changed = $true
-
- if ($null -ne $extra_scope_change) {
- try {
- $group = $group | Set-ADGroup -GroupScope $extra_scope_change -WhatIf:$check_mode -PassThru @extra_args
- } catch {
- Fail-Json $result "failed to change scope of group $name to $($scope): $($_.Exception.Message)"
- }
- }
- }
-
- # make sure our diff text is null if no change occurred
- if ($result.changed -eq $false) {
- $diff_text = $null
- }
- } else {
- # validate if scope is set
- if ($null -eq $scope) {
- Fail-Json $result "scope must be set when state=present and the group doesn't exist"
- }
-
- $diff_text += "+[$name]`n+Scope = $scope`n"
- $add_args = $extra_args.Clone()
- $add_args.Name = $name
- $add_args.GroupScope = $scope
-
- if ($null -ne $description) {
- $add_args.Description = $description
- $diff_text += "+Description = $description`n"
- }
-
- if ($null -ne $display_name) {
- $add_args.DisplayName = $display_name
- $diff_text += "+DisplayName = $display_name`n"
- }
-
- if ($null -ne $category) {
- $add_args.GroupCategory = $category
- $diff_text += "+GroupCategory = $category`n"
- }
-
- if ($null -ne $managed_by) {
- $add_args.ManagedBy = $managed_by
- $diff_text += "+ManagedBy = $managed_by`n"
- }
-
- if ($null -ne $attributes) {
- $add_args.OtherAttributes = $attributes
- foreach ($attribute in $attributes.GetEnumerator()) {
- $diff_text += "+$($attribute.Name) = $($attribute.Value)`n"
- }
- }
-
- if ($null -ne $organizational_unit) {
- $add_args.Path = $organizational_unit
- $diff_text += "+Path = $organizational_unit`n"
- }
-
- try {
- $group = New-AdGroup -WhatIf:$check_mode -PassThru @add_args
- } catch {
- Fail-Json $result "failed to create group $($name): $($_.Exception.Message)"
- }
- $result.changed = $true
- $result.created = $true
- }
-
- # set the protection value
- if ($null -ne $protect) {
- if (-not $check_mode) {
- $group = Get-ADGroup -Identity $name -Properties * @extra_args
- }
- $existing_protection_value = $group.ProtectedFromAccidentalDeletion
- if ($null -eq $existing_protection_value) {
- $existing_protection_value = $false
- }
- if ($existing_protection_value -ne $protect) {
- $diff_text += @"
--ProtectedFromAccidentalDeletion = $existing_protection_value
-+ProtectedFromAccidentalDeletion = $protect
-"@
-
- $group | Set-ADObject -ProtectedFromAccidentalDeletion $protect -WhatIf:$check_mode -PassThru @extra_args
- $result.changed = $true
- }
- }
-
- if ($diff_mode -and $null -ne $diff_text) {
- $result.diff.prepared = $diff_text
- }
-
- if (-not $check_mode) {
- $group = Get-ADGroup -Identity $name -Properties * @extra_args
- $result.sid = $group.SID.Value
- $result.description = $group.Description
- $result.distinguished_name = $group.DistinguishedName
- $result.display_name = $group.DisplayName
- $result.name = $group.Name
- $result.canonical_name = $group.CanonicalName
- $result.guid = $group.ObjectGUID
- $result.protected_from_accidental_deletion = $group.ProtectedFromAccidentalDeletion
- $result.managed_by = $group.ManagedBy
- $result.group_scope = ($group.GroupScope).ToString()
- $result.category = ($group.GroupCategory).ToString()
-
- if ($null -ne $attributes) {
- $result.attributes = @{}
- foreach ($attribute in $attributes.GetEnumerator()) {
- $attribute_name = $attribute.Name
- $result.attributes.$attribute_name = $group.$attribute_name
- }
- }
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_domain_group.py b/lib/ansible/modules/windows/win_domain_group.py
deleted file mode 100644
index 7a8792c1ad..0000000000
--- a/lib/ansible/modules/windows/win_domain_group.py
+++ /dev/null
@@ -1,242 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_domain_group
-version_added: '2.4'
-short_description: Creates, modifies or removes domain groups
-description:
-- Creates, modifies or removes groups in Active Directory.
-- For local groups, use the M(win_group) module instead.
-options:
- attributes:
- description:
- - A dict of custom LDAP attributes to set on the group.
- - This can be used to set custom attributes that are not exposed as module
- parameters, e.g. C(mail).
- - See the examples on how to format this parameter.
- type: dict
- category:
- description:
- - The category of the group, this is the value to assign to the LDAP
- C(groupType) attribute.
- - If a new group is created then C(security) will be used by default.
- type: str
- choices: [ distribution, security ]
- description:
- description:
- - The value to be assigned to the LDAP C(description) attribute.
- type: str
- display_name:
- description:
- - The value to assign to the LDAP C(displayName) attribute.
- type: str
- domain_username:
- description:
- - The username to use when interacting with AD.
- - If this is not set then the user Ansible used to log in with will be
- used instead.
- type: str
- domain_password:
- description:
- - The password for C(username).
- type: str
- domain_server:
- description:
- - Specifies the Active Directory Domain Services instance to connect to.
- - Can be in the form of an FQDN or NetBIOS name.
- - If not specified then the value is based on the domain of the computer
- running PowerShell.
- type: str
- version_added: '2.5'
- ignore_protection:
- description:
- - Will ignore the C(ProtectedFromAccidentalDeletion) flag when deleting or
- moving a group.
- - The module will fail if one of these actions need to occur and this value
- is set to C(no).
- type: bool
- default: no
- managed_by:
- description:
- - The value to be assigned to the LDAP C(managedBy) attribute.
- - This value can be in the forms C(Distinguished Name), C(objectGUID),
- C(objectSid) or C(sAMAccountName), see examples for more details.
- type: str
- name:
- description:
- - The name of the group to create, modify or remove.
- - This value can be in the forms C(Distinguished Name), C(objectGUID),
- C(objectSid) or C(sAMAccountName), see examples for more details.
- type: str
- required: yes
- organizational_unit:
- description:
- - The full LDAP path to create or move the group to.
- - This should be the path to the parent object to create or move the group to.
- - See examples for details of how this path is formed.
- type: str
- aliases: [ ou, path ]
- protect:
- description:
- - Will set the C(ProtectedFromAccidentalDeletion) flag based on this value.
- - This flag stops a user from deleting or moving a group to a different
- path.
- type: bool
- scope:
- description:
- - The scope of the group.
- - If C(state=present) and the group doesn't exist then this must be set.
- type: str
- choices: [domainlocal, global, universal]
- state:
- description:
- - If C(state=present) this module will ensure the group is created and is
- configured accordingly.
- - If C(state=absent) this module will delete the group if it exists
- type: str
- choices: [ absent, present ]
- default: present
-notes:
-- This must be run on a host that has the ActiveDirectory powershell module installed.
-seealso:
-- module: win_domain
-- module: win_domain_controller
-- module: win_domain_computer
-- module: win_domain_membership
-- module: win_domain_user
-- module: win_group
-- module: win_group_membership
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Ensure the group Cow exists using sAMAccountName
- win_domain_group:
- name: Cow
- scope: global
- path: OU=groups,DC=ansible,DC=local
-
-- name: Ensure the group Cow doesn't exist using the Distinguished Name
- win_domain_group:
- name: CN=Cow,OU=groups,DC=ansible,DC=local
- state: absent
-
-- name: Delete group ignoring the protection flag
- win_domain_group:
- name: Cow
- state: absent
- ignore_protection: yes
-
-- name: Create group with delete protection enabled and custom attributes
- win_domain_group:
- name: Ansible Users
- scope: domainlocal
- category: security
- attributes:
- mail: helpdesk@ansible.com
- wWWHomePage: www.ansible.com
- ignore_protection: yes
-
-- name: Change the OU of a group using the SID and ignore the protection flag
- win_domain_group:
- name: S-1-5-21-2171456218-3732823212-122182344-1189
- scope: global
- organizational_unit: OU=groups,DC=ansible,DC=local
- ignore_protection: yes
-
-- name: Add managed_by user
- win_domain_group:
- name: Group Name Here
- managed_by: Domain Admins
-
-- name: Add group and specify the AD domain services to use for the create
- win_domain_group:
- name: Test Group
- domain_username: user@CORP.ANSIBLE.COM
- domain_password: Password01!
- domain_server: corp-DC12.corp.ansible.com
- scope: domainlocal
-'''
-
-RETURN = r'''
-attributes:
- description: Custom attributes that were set by the module. This does not
- show all the custom attributes rather just the ones that were set by the
- module.
- returned: group exists and attributes are set on the module invocation
- type: dict
- sample:
- mail: 'helpdesk@ansible.com'
- wWWHomePage: 'www.ansible.com'
-canonical_name:
- description: The canonical name of the group.
- returned: group exists
- type: str
- sample: ansible.local/groups/Cow
-category:
- description: The Group type value of the group, i.e. Security or Distribution.
- returned: group exists
- type: str
- sample: Security
-description:
- description: The Description of the group.
- returned: group exists
- type: str
- sample: Group Description
-display_name:
- description: The Display name of the group.
- returned: group exists
- type: str
- sample: Users who connect through RDP
-distinguished_name:
- description: The full Distinguished Name of the group.
- returned: group exists
- type: str
- sample: CN=Cow,OU=groups,DC=ansible,DC=local
-group_scope:
- description: The Group scope value of the group.
- returned: group exists
- type: str
- sample: Universal
-guid:
- description: The guid of the group.
- returned: group exists
- type: str
- sample: 512a9adb-3fc0-4a26-9df0-e6ea1740cf45
-managed_by:
- description: The full Distinguished Name of the AD object that is set on the
- managedBy attribute.
- returned: group exists
- type: str
- sample: CN=Domain Admins,CN=Users,DC=ansible,DC=local
-name:
- description: The name of the group.
- returned: group exists
- type: str
- sample: Cow
-protected_from_accidental_deletion:
- description: Whether the group is protected from accidental deletion.
- returned: group exists
- type: bool
- sample: true
-sid:
- description: The Security ID of the group.
- returned: group exists
- type: str
- sample: S-1-5-21-2171456218-3732823212-122182344-1189
-created:
- description: Whether a group was created
- returned: always
- type: bool
- sample: true
-'''
diff --git a/lib/ansible/modules/windows/win_domain_group_membership.ps1 b/lib/ansible/modules/windows/win_domain_group_membership.ps1
deleted file mode 100644
index 878b9fc669..0000000000
--- a/lib/ansible/modules/windows/win_domain_group_membership.ps1
+++ /dev/null
@@ -1,131 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Marius Rieder <marius.rieder@scs.ch>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-try {
- Import-Module ActiveDirectory
-}
-catch {
- Fail-Json -obj @{} -message "win_domain_group_membership requires the ActiveDirectory PS module to be installed"
-}
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
-
-# Module control parameters
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent","pure"
-$domain_username = Get-AnsibleParam -obj $params -name "domain_username" -type "str"
-$domain_password = Get-AnsibleParam -obj $params -name "domain_password" -type "str" -failifempty ($null -ne $domain_username)
-$domain_server = Get-AnsibleParam -obj $params -name "domain_server" -type "str"
-
-# Group Membership parameters
-$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
-$members = Get-AnsibleParam -obj $params -name "members" -type "list" -failifempty $true
-
-# Filter ADObjects by ObjectClass
-$ad_object_class_filter = "(ObjectClass -eq 'user' -or ObjectClass -eq 'group' -or ObjectClass -eq 'computer' -or ObjectClass -eq 'msDS-ManagedServiceAccount')"
-
-$extra_args = @{}
-if ($null -ne $domain_username) {
- $domain_password = ConvertTo-SecureString $domain_password -AsPlainText -Force
- $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domain_username, $domain_password
- $extra_args.Credential = $credential
-}
-if ($null -ne $domain_server) {
- $extra_args.Server = $domain_server
-}
-
-$ADGroup = Get-ADGroup -Identity $name @extra_args
-
-$result = @{
- changed = $false
- added = [System.Collections.Generic.List`1[String]]@()
- removed = [System.Collections.Generic.List`1[String]]@()
-}
-if ($diff_mode) {
- $result.diff = @{}
-}
-
-$members_before = Get-AdGroupMember -Identity $ADGroup @extra_args
-$pure_members = [System.Collections.Generic.List`1[String]]@()
-
-foreach ($member in $members) {
- $extra_member_args = $extra_args.Clone()
- if ($member -match "\\"){
- $extra_member_args.Server = $member.Split("\")[0]
- $member = $member.Split("\")[1]
- }
- $group_member = Get-ADObject -Filter "SamAccountName -eq '$member' -and $ad_object_class_filter" -Properties objectSid, sAMAccountName @extra_member_args
- if (!$group_member) {
- Fail-Json -obj $result "Could not find domain user, group, service account or computer named $member"
- }
-
- if ($state -eq "pure") {
- $pure_members.Add($group_member.objectSid)
- }
-
- $user_in_group = $false
- foreach ($current_member in $members_before) {
- if ($current_member.sid -eq $group_member.objectSid) {
- $user_in_group = $true
- break
- }
- }
-
- if ($state -in @("present", "pure") -and !$user_in_group) {
- Add-ADPrincipalGroupMembership -Identity $group_member -MemberOf $ADGroup -WhatIf:$check_mode @extra_member_args
- $result.added.Add($group_member.SamAccountName)
- $result.changed = $true
- } elseif ($state -eq "absent" -and $user_in_group) {
- Remove-ADPrincipalGroupMembership -Identity $group_member -MemberOf $ADGroup -WhatIf:$check_mode -Confirm:$False @extra_member_args
- $result.removed.Add($group_member.SamAccountName)
- $result.changed = $true
- }
-}
-
-if ($state -eq "pure") {
- # Perform removals for existing group members not defined in $members
- $current_members = Get-AdGroupMember -Identity $ADGroup @extra_args
-
- foreach ($current_member in $current_members) {
- $user_to_remove = $true
- foreach ($pure_member in $pure_members) {
- if ($pure_member -eq $current_member.sid) {
- $user_to_remove = $false
- break
- }
- }
-
- if ($user_to_remove) {
- Remove-ADPrincipalGroupMembership -Identity $current_member -MemberOf $ADGroup -WhatIf:$check_mode -Confirm:$False
- $result.removed.Add($current_member.SamAccountName)
- $result.changed = $true
- }
- }
-}
-
-$final_members = Get-AdGroupMember -Identity $ADGroup @extra_args
-
-if ($final_members) {
- $result.members = [Array]$final_members.SamAccountName
-} else {
- $result.members = @()
-}
-
-if ($diff_mode -and $result.changed) {
- $result.diff.before = $members_before.SamAccountName | Out-String
- if (!$check_mode) {
- $result.diff.after = [Array]$final_members.SamAccountName | Out-String
- } else {
- $after = [System.Collections.Generic.List`1[String]]$result.members
- $result.removed | ForEach-Object { $after.Remove($_) > $null }
- $after.AddRange($result.added)
- $result.diff.after = $after | Out-String
- }
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_domain_group_membership.py b/lib/ansible/modules/windows/win_domain_group_membership.py
deleted file mode 100644
index be1b7f04af..0000000000
--- a/lib/ansible/modules/windows/win_domain_group_membership.py
+++ /dev/null
@@ -1,130 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Andrew Saraceni <andrew.saraceni@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_domain_group_membership
-version_added: "2.8"
-short_description: Manage Windows domain group membership
-description:
- - Allows the addition and removal of domain users
- and domain groups from/to a domain group.
-options:
- name:
- description:
- - Name of the domain group to manage membership on.
- type: str
- required: yes
- members:
- description:
- - A list of members to ensure are present/absent from the group.
- - The given names must be a SamAccountName of a user, group, service account, or computer.
- - For computers, you must add "$" after the name; for example, to add "Mycomputer" to a group, use "Mycomputer$" as the member.
- - If the member object is part of another domain in a multi-domain forest, you must add the domain and "\" in front of the name.
- type: list
- required: yes
- state:
- description:
- - Desired state of the members in the group.
- - When C(state) is C(pure), only the members specified will exist,
- and all other existing members not specified are removed.
- type: str
- choices: [ absent, present, pure ]
- default: present
- domain_username:
- description:
- - The username to use when interacting with AD.
- - If this is not set then the user Ansible used to log in with will be
- used instead when using CredSSP or Kerberos with credential delegation.
- type: str
- domain_password:
- description:
- - The password for I(username).
- type: str
- domain_server:
- description:
- - Specifies the Active Directory Domain Services instance to connect to.
- - Can be in the form of an FQDN or NetBIOS name.
- - If not specified then the value is based on the domain of the computer
- running PowerShell.
- type: str
-notes:
-- This must be run on a host that has the ActiveDirectory powershell module installed.
-seealso:
-- module: win_domain_user
-- module: win_domain_group
-author:
- - Marius Rieder (@jiuka)
-'''
-
-EXAMPLES = r'''
-- name: Add a domain user/group to a domain group
- win_domain_group_membership:
- name: Foo
- members:
- - Bar
- state: present
-
-- name: Remove a domain user/group from a domain group
- win_domain_group_membership:
- name: Foo
- members:
- - Bar
- state: absent
-
-- name: Ensure only a domain user/group exists in a domain group
- win_domain_group_membership:
- name: Foo
- members:
- - Bar
- state: pure
-
-- name: Add a computer to a domain group
- win_domain_group_membership:
- name: Foo
- members:
- - DESKTOP$
- state: present
-
-- name: Add a domain user/group from another Domain in the multi-domain forest to a domain group
- win_domain_group_membership:
- domain_server: DomainAAA.cloud
- name: GroupinDomainAAA
- members:
- - DomainBBB.cloud\UserInDomainBBB
- state: Present
-
-'''
-
-RETURN = r'''
-name:
- description: The name of the target domain group.
- returned: always
- type: str
- sample: Domain-Admins
-added:
- description: A list of members added when C(state) is C(present) or
- C(pure); this is empty if no members are added.
- returned: success and C(state) is C(present) or C(pure)
- type: list
- sample: ["UserName", "GroupName"]
-removed:
- description: A list of members removed when C(state) is C(absent) or
- C(pure); this is empty if no members are removed.
- returned: success and C(state) is C(absent) or C(pure)
- type: list
- sample: ["UserName", "GroupName"]
-members:
- description: A list of all domain group members at completion; this is empty
- if the group contains no members.
- returned: success
- type: list
- sample: ["UserName", "GroupName"]
-'''
diff --git a/lib/ansible/modules/windows/win_domain_object_info.ps1 b/lib/ansible/modules/windows/win_domain_object_info.ps1
deleted file mode 100644
index f8f6f6457b..0000000000
--- a/lib/ansible/modules/windows/win_domain_object_info.ps1
+++ /dev/null
@@ -1,271 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2020, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.AddType
-
-$spec = @{
- options = @{
- domain_password = @{ type = 'str'; no_log = $true }
- domain_server = @{ type = 'str' }
- domain_username = @{ type = 'str' }
- filter = @{ type = 'str' }
- identity = @{ type = 'str' }
- include_deleted = @{ type = 'bool'; default = $false }
- ldap_filter = @{ type = 'str' }
- properties = @{ type = 'list'; elements = 'str' }
- search_base = @{ type = 'str' }
- search_scope = @{ type = 'str'; choices = @('base', 'one_level', 'subtree') }
- }
- supports_check_mode = $true
- mutually_exclusive = @(
- @('filter', 'identity', 'ldap_filter'),
- @('identity', 'search_base'),
- @('identity', 'search_scope')
- )
- required_one_of = @(
- ,@('filter', 'identity', 'ldap_filter')
- )
- required_together = @(,@('domain_username', 'domain_password'))
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$module.Result.objects = @() # Always ensure this is returned even in a failure.
-
-$domainServer = $module.Params.domain_server
-$domainPassword = $module.Params.domain_password
-$domainUsername = $module.Params.domain_username
-$filter = $module.Params.filter
-$identity = $module.Params.identity
-$includeDeleted = $module.Params.include_deleted
-$ldapFilter = $module.Params.ldap_filter
-$properties = $module.Params.properties
-$searchBase = $module.Params.search_base
-$searchScope = $module.Params.search_scope
-
-$credential = $null
-if ($domainUsername) {
- $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList @(
- $domainUsername,
- (ConvertTo-SecureString -AsPlainText -Force -String $domainPassword)
- )
-}
-
-Add-CSharpType -References @'
-using System;
-
-namespace Ansible.WinDomainObjectInfo
-{
- [Flags]
- public enum UserAccountControl : int
- {
- ADS_UF_SCRIPT = 0x00000001,
- ADS_UF_ACCOUNTDISABLE = 0x00000002,
- ADS_UF_HOMEDIR_REQUIRED = 0x00000008,
- ADS_UF_LOCKOUT = 0x00000010,
- ADS_UF_PASSWD_NOTREQD = 0x00000020,
- ADS_UF_PASSWD_CANT_CHANGE = 0x00000040,
- ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0x00000080,
- ADS_UF_TEMP_DUPLICATE_ACCOUNT = 0x00000100,
- ADS_UF_NORMAL_ACCOUNT = 0x00000200,
- ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 0x00000800,
- ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x00001000,
- ADS_UF_SERVER_TRUST_ACCOUNT = 0x00002000,
- ADS_UF_DONT_EXPIRE_PASSWD = 0x00010000,
- ADS_UF_MNS_LOGON_ACCOUNT = 0x00020000,
- ADS_UF_SMARTCARD_REQUIRED = 0x00040000,
- ADS_UF_TRUSTED_FOR_DELEGATION = 0x00080000,
- ADS_UF_NOT_DELEGATED = 0x00100000,
- ADS_UF_USE_DES_KEY_ONLY = 0x00200000,
- ADS_UF_DONT_REQUIRE_PREAUTH = 0x00400000,
- ADS_UF_PASSWORD_EXPIRED = 0x00800000,
- ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x01000000,
- }
-
- public enum sAMAccountType : int
- {
- SAM_DOMAIN_OBJECT = 0x00000000,
- SAM_GROUP_OBJECT = 0x10000000,
- SAM_NON_SECURITY_GROUP_OBJECT = 0x10000001,
- SAM_ALIAS_OBJECT = 0x20000000,
- SAM_NON_SECURITY_ALIAS_OBJECT = 0x20000001,
- SAM_USER_OBJECT = 0x30000000,
- SAM_NORMAL_USER_ACCOUNT = 0x30000000,
- SAM_MACHINE_ACCOUNT = 0x30000001,
- SAM_TRUST_ACCOUNT = 0x30000002,
- SAM_APP_BASIC_GROUP = 0x40000000,
- SAM_APP_QUERY_GROUP = 0x40000001,
- SAM_ACCOUNT_TYPE_MAX = 0x7fffffff,
- }
-}
-'@
-
-Function ConvertTo-OutputValue {
- [CmdletBinding()]
- Param (
- [Parameter(Mandatory=$true)]
- [AllowNull()]
- [Object]
- $InputObject
- )
-
- if ($InputObject -is [System.Security.Principal.SecurityIdentifier]) {
- # Syntax: SID - Only serialize the SID as a string and not the other metadata properties.
- $sidInfo = @{
- Sid = $InputObject.Value
- }
-
- # Try and map the SID to the account name, this may fail if the SID is invalid or not mappable.
- try {
- $sidInfo.Name = $InputObject.Translate([System.Security.Principal.NTAccount]).Value
- } catch [System.Security.Principal.IdentityNotMappedException] {
- $sidInfo.Name = $null
- }
-
- $sidInfo
- } elseif ($InputObject -is [Byte[]]) {
- # Syntax: Octet String - By default will serialize as a list of decimal values per byte, instead return a
- # Base64 string as Ansible can easily parse that.
- [System.Convert]::ToBase64String($InputObject)
- } elseif ($InputObject -is [DateTime]) {
- # Syntax: UTC Coded Time - .NET DateTimes serialized as in the form "Date(FILETIME)" which isn't easily
- # parsable by Ansible, instead return as an ISO 8601 string in the UTC timezone.
- [TimeZoneInfo]::ConvertTimeToUtc($InputObject).ToString("o")
- } elseif ($InputObject -is [System.Security.AccessControl.ObjectSecurity]) {
- # Complex object which isn't easily serializable. Instead we should just return the SDDL string. If a user
- # needs to parse this then they really need to reprocess the SDDL string and process their results on another
- # win_shell task.
- $InputObject.GetSecurityDescriptorSddlForm(([System.Security.AccessControl.AccessControlSections]::All))
- } else {
- # Syntax: (All Others) - The default serialization handling of other syntaxes are fine, don't do anything.
- $InputObject
- }
-}
-
-<#
-Calling Get-ADObject that returns multiple objects with -Properties * will only return the properties that were set on
-the first found object. To counter this problem we will first call Get-ADObject to list all the objects that match the
-filter specified then get the properties on each object.
-#>
-
-$commonParams = @{
- IncludeDeletedObjects = $includeDeleted
-}
-
-if ($credential) {
- $commonParams.Credential = $credential
-}
-
-if ($domainServer) {
- $commonParams.Server = $domainServer
-}
-
-# First get the IDs for all the AD objects that match the filter specified.
-$getParams = @{
- Properties = @('DistinguishedName', 'ObjectGUID')
-}
-
-if ($filter) {
- $getParams.Filter = $filter
-} elseif ($identity) {
- $getParams.Identity = $identity
-} elseif ($ldapFilter) {
- $getParams.LDAPFilter = $ldapFilter
-}
-
-# Explicit check on $null as an empty string is different from not being set.
-if ($null -ne $searchBase) {
- $getParams.SearchBase = $searchbase
-}
-
-if ($searchScope) {
- $getParams.SearchScope = switch($searchScope) {
- base { 'Base' }
- one_level { 'OneLevel' }
- subtree { 'Subtree' }
- }
-}
-
-try {
- # We run this in a custom PowerShell pipeline so that users of this module can't use any of the variables defined
- # above in their filter. While the cmdlet won't execute sub expressions we don't want anyone implicitly relying on
- # a defined variable in this module in case we ever change the name or remove it.
- $ps = [PowerShell]::Create()
- $null = $ps.AddCommand('Get-ADObject').AddParameters($commonParams).AddParameters($getParams)
- $null = $ps.AddCommand('Select-Object').AddParameter('Property', @('DistinguishedName', 'ObjectGUID'))
-
- $foundGuids = @($ps.Invoke())
-} catch {
- # Because we ran in a pipeline we can't catch ADIdentityNotFoundException. Instead just get the base exception and
- # do the error checking on that.
- if ($_.Exception.GetBaseException() -is [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]) {
- $foundGuids = @()
- } else {
- # The exception is from the .Invoke() call, compare on the InnerException which was what was actually raised by
- # the pipeline.
- $innerException = $_.Exception.InnerException.InnerException
- if ($innerException -is [Microsoft.ActiveDirectory.Management.ADServerDownException]) {
- # Point users in the direction of the double hop problem as that is what is typically the cause of this.
- $msg = "Failed to contact the AD server, this could be caused by the double hop problem over WinRM. "
- $msg += "Try using the module with auth as Kerberos with credential delegation or CredSSP, become, or "
- $msg += "defining the domain_username and domain_password module parameters."
- $module.FailJson($msg, $innerException)
- } else {
- throw $innerException
- }
- }
-}
-
-$getParams = @{}
-if ($properties) {
- $getParams.Properties = $properties
-}
-$module.Result.objects = @(foreach ($adId in $foundGuids) {
- try {
- $adObject = Get-ADObject @commonParams @getParams -Identity $adId.ObjectGUID
- } catch {
- $msg = "Failed to retrieve properties for AD Object '$($adId.DistinguishedName)': $($_.Exception.Message)"
- $module.Warn($msg)
- continue
- }
-
- $propertyNames = $adObject.PropertyNames
- $propertyNames += ($properties | Where-Object { $_ -ne '*' })
-
- # Now process each property to an easy to represent string
- $filteredObject = [Ordered]@{}
- foreach ($name in ($propertyNames | Sort-Object)) {
- # In the case of explicit properties that were asked for but weren't set, Get-ADObject won't actually return
- # the property so this is a defensive check against that scenario.
- if (-not $adObject.PSObject.Properties.Name.Contains($name)) {
- $filteredObject.$name = $null
- continue
- }
-
- $value = $adObject.$name
- if ($value -is [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]) {
- $value = foreach ($v in $value) {
- ConvertTo-OutputValue -InputObject $v
- }
- } else {
- $value = ConvertTo-OutputValue -InputObject $value
- }
- $filteredObject.$name = $value
-
- # For these 2 properties, add an _AnsibleFlags attribute which contains the enum strings that are set.
- if ($name -eq 'sAMAccountType') {
- $enumValue = [Ansible.WinDomainObjectInfo.sAMAccountType]$value
- $filteredObject.'sAMAccountType_AnsibleFlags' = $enumValue.ToString() -split ', '
- } elseif ($name -eq 'userAccountControl') {
- $enumValue = [Ansible.WinDomainObjectInfo.UserAccountControl]$value
- $filteredObject.'userAccountControl_AnsibleFlags' = $enumValue.ToString() -split ', '
- }
- }
-
- $filteredObject
-})
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_domain_object_info.py b/lib/ansible/modules/windows/win_domain_object_info.py
deleted file mode 100644
index 008b141b1b..0000000000
--- a/lib/ansible/modules/windows/win_domain_object_info.py
+++ /dev/null
@@ -1,162 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2020, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_domain_object_info
-version_added: '2.10'
-short_description: Gather information an Active Directory object
-description:
-- Gather information about multiple Active Directory object(s).
-options:
- domain_password:
- description:
- - The password for C(domain_username).
- type: str
- domain_server:
- description:
- - Specified the Active Directory Domain Services instance to connect to.
- - Can be in the form of an FQDN or NetBIOS name.
- - If not specified then the value is based on the default domain of the computer running PowerShell.
- type: str
- domain_username:
- description:
- - The username to use when interacting with AD.
- - If this is not set then the user that is used for authentication will be the connection user.
- - Ansible will be unable to use the connection user unless auth is Kerberos with credential delegation or CredSSP,
- or become is used on the task.
- type: str
- filter:
- description:
- - Specifies a query string using the PowerShell Expression Language syntax.
- - This follows the same rules and formatting as the C(-Filter) parameter for the PowerShell AD cmdlets exception
- there is no variable substitutions.
- - This is mutually exclusive with I(identity) and I(ldap_filter).
- type: str
- identity:
- description:
- - Specifies a single Active Directory object by its distinguished name or its object GUID.
- - This is mutually exclusive with I(filter) and I(ldap_filter).
- - This cannot be used with either the I(search_base) or I(search_scope) options.
- type: str
- include_deleted:
- description:
- - Also search for deleted Active Directory objects.
- default: no
- type: bool
- ldap_filter:
- description:
- - Like I(filter) but this is a tradiitional LDAP query string to filter the objects to return.
- - This is mutually exclusive with I(filter) and I(identity).
- type: str
- properties:
- description:
- - A list of properties to return.
- - If a property is C(*), all properties that have a set value on the AD object will be returned.
- - If a property is valid on the object but not set, it is only returned if defined explicitly in this option list.
- - The properties C(DistinguishedName), C(Name), C(ObjectClass), and C(ObjectGUID) are always returned.
- - Specifying multiple properties can have a performance impact, it is best to only return what is needed.
- - If an invalid property is specified then the module will display a warning for each object it is invalid on.
- type: list
- elements: str
- search_base:
- description:
- - Specify the Active Directory path to search for objects in.
- - This cannot be set with I(identity).
- - By default the search base is the default naming context of the target AD instance which is the DN returned by
- "(Get-ADRootDSE).defaultNamingContext".
- type: str
- search_scope:
- description:
- - Specify the scope of when searching for an object in the C(search_base).
- - C(base) will limit the search to the base object so the maximum number of objects returned is always one. This
- will not search any objects inside a container..
- - C(one_level) will search the current path and any immediate objects in that path.
- - C(subtree) will search the current path and all objects of that path recursively.
- - This cannot be set with I(identity).
- choices:
- - base
- - one_level
- - subtree
- type: str
-notes:
-- The C(sAMAccountType_AnsibleFlags) and C(userAccountControl_AnsibleFlags) return property is something set by the
- module itself as an easy way to view what those flags represent. These properties cannot be used as part of the
- I(filter) or I(ldap_filter) and are automatically added if those properties were requested.
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Get all properties for the specified account using its DistinguishedName
- win_domain_object_info:
- identity: CN=Username,CN=Users,DC=domain,DC=com
- properties: '*'
-
-- name: Get the SID for all user accounts as a filter
- win_domain_object_info:
- filter: ObjectClass -eq 'user' -and objectCategory -eq 'Person'
- properties:
- - objectSid
-
-- name: Get the SID for all user accounts as a LDAP filter
- win_domain_object_info:
- ldap_filter: (&(objectClass=user)(objectCategory=Person))
- properties:
- - objectSid
-
-- name: Search all computer accounts in a specific path that were added after February 1st
- win_domain_object_info:
- filter: objectClass -eq 'computer' -and whenCreated -gt '20200201000000.0Z'
- properties: '*'
- search_scope: one_level
- search_base: CN=Computers,DC=domain,DC=com
-'''
-
-RETURN = r'''
-objects:
- description:
- - A list of dictionaries that are the Active Directory objects found and the properties requested.
- - The dict's keys are the property name and the value is the value for the property.
- - All date properties are return in the ISO 8601 format in the UTC timezone.
- - All SID properties are returned as a dict with the keys C(Sid) as the SID string and C(Name) as the translated SID
- account name.
- - All byte properties are returned as a base64 string.
- - All security descriptor properties are returned as the SDDL string of that descriptor.
- - The properties C(DistinguishedName), C(Name), C(ObjectClass), and C(ObjectGUID) are always returned.
- returned: always
- type: list
- elements: dict
- sample: |
- [{
- "accountExpires": 0,
- "adminCount": 1,
- "CanonicalName": "domain.com/Users/Administrator",
- "CN": "Administrator",
- "Created": "2020-01-13T09:03:22.0000000Z",
- "Description": "Built-in account for administering computer/domain",
- "DisplayName": null,
- "DistinguishedName": "CN=Administrator,CN=Users,DC=domain,DC=com",
- "memberOf": [
- "CN=Group Policy Creator Owners,CN=Users,DC=domain,DC=com",
- "CN=Domain Admins",CN=Users,DC=domain,DC=com"
- ],
- "Name": "Administrator",
- "nTSecurityDescriptor": "O:DAG:DAD:PAI(A;;LCRPLORC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCDCLCSWRPWPLOCRSDRCWDWO;;;BA)",
- "ObjectCategory": "CN=Person,CN=Schema,CN=Configuration,DC=domain,DC=com",
- "ObjectClass": "user",
- "ObjectGUID": "c8c6569e-4688-4f3c-8462-afc4ff60817b",
- "objectSid": {
- "Sid": "S-1-5-21-2959096244-3298113601-420842770-500",
- "Name": "DOMAIN\Administrator"
- },
- "sAMAccountName": "Administrator",
- }]
-'''
diff --git a/lib/ansible/modules/windows/win_domain_user.ps1 b/lib/ansible/modules/windows/win_domain_user.ps1
deleted file mode 100644
index da690d7b16..0000000000
--- a/lib/ansible/modules/windows/win_domain_user.ps1
+++ /dev/null
@@ -1,384 +0,0 @@
-#!powershell
-
-# 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.AccessToken
-
-Function Test-Credential {
- param(
- [String]$Username,
- [String]$Password,
- [String]$Domain = $null
- )
- if (($Username.ToCharArray()) -contains [char]'@') {
- # UserPrincipalName
- $Domain = $null # force $Domain to be null, to prevent undefined behaviour, as a domain name is already included in the username
- } elseif (($Username.ToCharArray()) -contains [char]'\') {
- # Pre Win2k Account Name
- $Username = ($Username -split '\')[0]
- $Domain = ($Username -split '\')[1]
- } else {
- # No domain provided, so maybe local user, or domain specified separately.
- }
-
- try {
- $handle = [Ansible.AccessToken.TokenUtil]::LogonUser($Username, $Domain, $Password, "Network", "Default")
- $handle.Dispose()
- return $true
- } catch [Ansible.AccessToken.Win32Exception] {
- # following errors indicate the creds are correct but the user was
- # unable to log on for other reasons, which we don't care about
- $success_codes = @(
- 0x0000052F, # ERROR_ACCOUNT_RESTRICTION
- 0x00000530, # ERROR_INVALID_LOGON_HOURS
- 0x00000531, # ERROR_INVALID_WORKSTATION
- 0x00000569 # ERROR_LOGON_TYPE_GRANTED
- )
- $failed_codes = @(
- 0x0000052E, # ERROR_LOGON_FAILURE
- 0x00000532 # ERROR_PASSWORD_EXPIRED
- )
-
- if ($_.Exception.NativeErrorCode -in $failed_codes) {
- return $false
- } elseif ($_.Exception.NativeErrorCode -in $success_codes) {
- return $true
- } else {
- # an unknown failure, reraise exception
- throw $_
- }
- }
-}
-
-try {
- Import-Module ActiveDirectory
- }
- catch {
- Fail-Json $result "Failed to import ActiveDirectory PowerShell module. This module should be run on a domain controller, and the ActiveDirectory module must be available."
- }
-
-$result = @{
- changed = $false
- created = $false
- password_updated = $false
-}
-
-$ErrorActionPreference = "Stop"
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -default $false
-
-# Module control parameters
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent","query"
-$update_password = Get-AnsibleParam -obj $params -name "update_password" -type "str" -default "always" -validateset "always","on_create","when_changed"
-$groups_action = Get-AnsibleParam -obj $params -name "groups_action" -type "str" -default "replace" -validateset "add","remove","replace"
-$domain_username = Get-AnsibleParam -obj $params -name "domain_username" -type "str"
-$domain_password = Get-AnsibleParam -obj $params -name "domain_password" -type "str" -failifempty ($null -ne $domain_username)
-$domain_server = Get-AnsibleParam -obj $params -name "domain_server" -type "str"
-
-# User account parameters
-$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
-$identity = Get-AnsibleParam -obj $params -name "identity" -type "str" -default $name
-$description = Get-AnsibleParam -obj $params -name "description" -type "str"
-$password = Get-AnsibleParam -obj $params -name "password" -type "str"
-$password_expired = Get-AnsibleParam -obj $params -name "password_expired" -type "bool"
-$password_never_expires = Get-AnsibleParam -obj $params -name "password_never_expires" -type "bool"
-$user_cannot_change_password = Get-AnsibleParam -obj $params -name "user_cannot_change_password" -type "bool"
-$account_locked = Get-AnsibleParam -obj $params -name "account_locked" -type "bool"
-$groups = Get-AnsibleParam -obj $params -name "groups" -type "list"
-$enabled = Get-AnsibleParam -obj $params -name "enabled" -type "bool" -default $true
-$path = Get-AnsibleParam -obj $params -name "path" -type "str"
-$upn = Get-AnsibleParam -obj $params -name "upn" -type "str"
-
-# User informational parameters
-$user_info = @{
- GivenName = Get-AnsibleParam -obj $params -name "firstname" -type "str"
- Surname = Get-AnsibleParam -obj $params -name "surname" -type "str"
- Company = Get-AnsibleParam -obj $params -name "company" -type "str"
- EmailAddress = Get-AnsibleParam -obj $params -name "email" -type "str"
- StreetAddress = Get-AnsibleParam -obj $params -name "street" -type "str"
- City = Get-AnsibleParam -obj $params -name "city" -type "str"
- State = Get-AnsibleParam -obj $params -name "state_province" -type "str"
- PostalCode = Get-AnsibleParam -obj $params -name "postal_code" -type "str"
- Country = Get-AnsibleParam -obj $params -name "country" -type "str"
-}
-
-# Additional attributes
-$attributes = Get-AnsibleParam -obj $params -name "attributes"
-
-# Parameter validation
-If ($null -ne $account_locked -and $account_locked) {
- Fail-Json $result "account_locked must be set to 'no' if provided"
-}
-If (($null -ne $password_expired) -and ($null -ne $password_never_expires)) {
- Fail-Json $result "password_expired and password_never_expires are mutually exclusive but have both been set"
-}
-
-$extra_args = @{}
-if ($null -ne $domain_username) {
- $domain_password = ConvertTo-SecureString $domain_password -AsPlainText -Force
- $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domain_username, $domain_password
- $extra_args.Credential = $credential
-}
-if ($null -ne $domain_server) {
- $extra_args.Server = $domain_server
-}
-
-Function Get-PrincipalGroups {
- Param ($identity, $args_extra)
- try{
- $groups = Get-ADPrincipalGroupMembership -Identity $identity @args_extra -ErrorAction Stop
- } catch {
- Add-Warning -obj $result -message "Failed to enumerate user groups but continuing on.: $($_.Exception.Message)"
- return @()
- }
-
- $result_groups = foreach ($group in $groups) {
- $group.DistinguishedName
- }
- return $result_groups
-}
-
-try {
- $user_obj = Get-ADUser -Identity $identity -Properties * @extra_args
- $user_guid = $user_obj.ObjectGUID
-}
-catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
- $user_obj = $null
- $user_guid = $null
-}
-
-If ($state -eq 'present') {
- # Ensure user exists
- $new_user = $false
-
- # If the account does not exist, create it
- If (-not $user_obj) {
- $create_args = @{}
- $create_args.Name = $name
- If ($null -ne $path){
- $create_args.Path = $path
- }
- If ($null -ne $upn){
- $create_args.UserPrincipalName = $upn
- $create_args.SamAccountName = $upn.Split('@')[0]
- }
- $user_obj = New-ADUser @create_args -WhatIf:$check_mode -PassThru @extra_args
- $user_guid = $user_obj.ObjectGUID
- $new_user = $true
- $result.created = $true
- $result.changed = $true
- If ($check_mode) {
- Exit-Json $result
- }
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- }
-
- If ($password) {
- # Don't unnecessary check for working credentials.
- # Set the password if we need to.
- # For new_users there is also no difference between always and when_changed
- # so we don't need to differentiate between this two states.
- If ($new_user -or ($update_password -eq "always")) {
- $set_new_credentials = $true
- } elseif ($update_password -eq "when_changed") {
- $set_new_credentials = -not (Test-Credential -Username $user_obj.UserPrincipalName -Password $password)
- } else {
- $set_new_credentials = $false
- }
- If ($set_new_credentials) {
- $secure_password = ConvertTo-SecureString $password -AsPlainText -Force
- Set-ADAccountPassword -Identity $user_guid -Reset:$true -Confirm:$false -NewPassword $secure_password -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.password_updated = $true
- $result.changed = $true
- }
- }
-
- # Configure password policies
- If (($null -ne $password_never_expires) -and ($password_never_expires -ne $user_obj.PasswordNeverExpires)) {
- Set-ADUser -Identity $user_guid -PasswordNeverExpires $password_never_expires -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
- If (($null -ne $password_expired) -and ($password_expired -ne $user_obj.PasswordExpired)) {
- Set-ADUser -Identity $user_guid -ChangePasswordAtLogon $password_expired -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
- If (($null -ne $user_cannot_change_password) -and ($user_cannot_change_password -ne $user_obj.CannotChangePassword)) {
- Set-ADUser -Identity $user_guid -CannotChangePassword $user_cannot_change_password -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
-
- # Assign other account settings
- If (($null -ne $upn) -and ($upn -ne $user_obj.UserPrincipalName)) {
- Set-ADUser -Identity $user_guid -UserPrincipalName $upn -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
- If (($null -ne $description) -and ($description -ne $user_obj.Description)) {
- Set-ADUser -Identity $user_guid -description $description -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
- If ($enabled -ne $user_obj.Enabled) {
- Set-ADUser -Identity $user_guid -Enabled $enabled -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
- If ((-not $account_locked) -and ($user_obj.LockedOut -eq $true)) {
- Unlock-ADAccount -Identity $user_guid -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
-
- # Set user information
- Foreach ($key in $user_info.Keys) {
- If ($null -eq $user_info[$key]) {
- continue
- }
- $value = $user_info[$key]
- If ($value -ne $user_obj.$key) {
- $set_args = $extra_args.Clone()
- $set_args.$key = $value
- Set-ADUser -Identity $user_guid -WhatIf:$check_mode @set_args
- $result.changed = $true
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- }
- }
-
- # Set additional attributes
- $set_args = $extra_args.Clone()
- $run_change = $false
- if ($null -ne $attributes) {
- $add_attributes = @{}
- $replace_attributes = @{}
- foreach ($attribute in $attributes.GetEnumerator()) {
- $attribute_name = $attribute.Name
- $attribute_value = $attribute.Value
-
- $valid_property = [bool]($user_obj.PSobject.Properties.name -eq $attribute_name)
- if ($valid_property) {
- $existing_value = $user_obj.$attribute_name
- if ($existing_value -cne $attribute_value) {
- $replace_attributes.$attribute_name = $attribute_value
- }
- } else {
- $add_attributes.$attribute_name = $attribute_value
- }
- }
- if ($add_attributes.Count -gt 0) {
- $set_args.Add = $add_attributes
- $run_change = $true
- }
- if ($replace_attributes.Count -gt 0) {
- $set_args.Replace = $replace_attributes
- $run_change = $true
- }
- }
-
- if ($run_change) {
- try {
- $user_obj = $user_obj | Set-ADUser -WhatIf:$check_mode -PassThru @set_args
- } catch {
- Fail-Json $result "failed to change user $($name): $($_.Exception.Message)"
- }
- $result.changed = $true
- }
-
-
- # Configure group assignment
- If ($null -ne $groups) {
- $group_list = $groups
-
- $groups = @()
- Foreach ($group in $group_list) {
- $groups += (Get-ADGroup -Identity $group @extra_args).DistinguishedName
- }
-
- $assigned_groups = Get-PrincipalGroups $user_guid $extra_args
-
- switch ($groups_action) {
- "add" {
- Foreach ($group in $groups) {
- If (-not ($assigned_groups -Contains $group)) {
- Add-ADGroupMember -Identity $group -Members $user_guid -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
- }
- }
- "remove" {
- Foreach ($group in $groups) {
- If ($assigned_groups -Contains $group) {
- Remove-ADGroupMember -Identity $group -Members $user_guid -Confirm:$false -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
- }
- }
- "replace" {
- Foreach ($group in $assigned_groups) {
- If (($group -ne $user_obj.PrimaryGroup) -and -not ($groups -Contains $group)) {
- Remove-ADGroupMember -Identity $group -Members $user_guid -Confirm:$false -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
- }
- Foreach ($group in $groups) {
- If (-not ($assigned_groups -Contains $group)) {
- Add-ADGroupMember -Identity $group -Members $user_guid -WhatIf:$check_mode @extra_args
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.changed = $true
- }
- }
- }
- }
- }
-} ElseIf ($state -eq 'absent') {
- # Ensure user does not exist
- If ($user_obj) {
- Remove-ADUser $user_obj -Confirm:$false -WhatIf:$check_mode @extra_args
- $result.changed = $true
- If ($check_mode) {
- Exit-Json $result
- }
- $user_obj = $null
- }
-}
-
-If ($user_obj) {
- $user_obj = Get-ADUser -Identity $user_guid -Properties * @extra_args
- $result.name = $user_obj.Name
- $result.firstname = $user_obj.GivenName
- $result.surname = $user_obj.Surname
- $result.enabled = $user_obj.Enabled
- $result.company = $user_obj.Company
- $result.street = $user_obj.StreetAddress
- $result.email = $user_obj.EmailAddress
- $result.city = $user_obj.City
- $result.state_province = $user_obj.State
- $result.country = $user_obj.Country
- $result.postal_code = $user_obj.PostalCode
- $result.distinguished_name = $user_obj.DistinguishedName
- $result.description = $user_obj.Description
- $result.password_expired = $user_obj.PasswordExpired
- $result.password_never_expires = $user_obj.PasswordNeverExpires
- $result.user_cannot_change_password = $user_obj.CannotChangePassword
- $result.account_locked = $user_obj.LockedOut
- $result.sid = [string]$user_obj.SID
- $result.upn = $user_obj.UserPrincipalName
- $result.groups = Get-PrincipalGroups $user_guid $extra_args
- $result.msg = "User '$name' is present"
- $result.state = "present"
-}
-Else {
- $result.name = $name
- $result.msg = "User '$name' is absent"
- $result.state = "absent"
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_domain_user.py b/lib/ansible/modules/windows/win_domain_user.py
deleted file mode 100644
index 1880ece176..0000000000
--- a/lib/ansible/modules/windows/win_domain_user.py
+++ /dev/null
@@ -1,376 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_domain_user
-version_added: '2.4'
-short_description: Manages Windows Active Directory user accounts
-description:
- - Manages Windows Active Directory user accounts.
-options:
- name:
- description:
- - Name of the user to create, remove or modify.
- type: str
- required: true
- identity:
- description:
- - Identity parameter used to find the User in the Active Directory.
- - This value can be in the forms C(Distinguished Name), C(objectGUID),
- C(objectSid) or C(sAMAccountName).
- - Default to C(name) if not set.
- type: str
- version_added: '2.10'
- state:
- description:
- - When C(present), creates or updates the user account.
- - When C(absent), removes the user account if it exists.
- - When C(query), retrieves the user account details without making any changes.
- type: str
- choices: [ absent, present, query ]
- default: present
- enabled:
- description:
- - C(yes) will enable the user account.
- - C(no) will disable the account.
- type: bool
- default: yes
- account_locked:
- description:
- - C(no) will unlock the user account if locked.
- - Note that there is not a way to lock an account as an administrator.
- - Accounts are locked due to user actions; as an admin, you may only unlock a locked account.
- - If you wish to administratively disable an account, set I(enabled) to C(no).
- choices: [ no ]
- description:
- description:
- - Description of the user
- type: str
- groups:
- description:
- - Adds or removes the user from this list of groups,
- depending on the value of I(groups_action).
- - To remove all but the Principal Group, set C(groups=<principal group name>) and
- I(groups_action=replace).
- - Note that users cannot be removed from their principal group (for example, "Domain Users").
- type: list
- groups_action:
- description:
- - If C(add), the user is added to each group in I(groups) where not already a member.
- - If C(remove), the user is removed from each group in I(groups).
- - If C(replace), the user is added as a member of each group in
- I(groups) and removed from any other groups.
- type: str
- choices: [ add, remove, replace ]
- default: replace
- password:
- description:
- - Optionally set the user's password to this (plain text) value.
- - To enable an account - I(enabled) - a password must already be
- configured on the account, or you must provide a password here.
- type: str
- update_password:
- description:
- - C(always) will always update passwords.
- - C(on_create) will only set the password for newly created users.
- - C(when_changed) will only set the password when changed (added in ansible 2.9).
- type: str
- choices: [ always, on_create, when_changed ]
- default: always
- password_expired:
- description:
- - C(yes) will require the user to change their password at next login.
- - C(no) will clear the expired password flag.
- - This is mutually exclusive with I(password_never_expires).
- type: bool
- password_never_expires:
- description:
- - C(yes) will set the password to never expire.
- - C(no) will allow the password to expire.
- - This is mutually exclusive with I(password_expired).
- type: bool
- user_cannot_change_password:
- description:
- - C(yes) will prevent the user from changing their password.
- - C(no) will allow the user to change their password.
- type: bool
- firstname:
- description:
- - Configures the user's first name (given name).
- type: str
- surname:
- description:
- - Configures the user's last name (surname).
- type: str
- company:
- description:
- - Configures the user's company name.
- type: str
- upn:
- description:
- - Configures the User Principal Name (UPN) for the account.
- - This is not required, but is best practice to configure for modern
- versions of Active Directory.
- - The format is C(<username>@<domain>).
- type: str
- email:
- description:
- - Configures the user's email address.
- - This is a record in AD and does not do anything to configure any email
- servers or systems.
- type: str
- street:
- description:
- - Configures the user's street address.
- type: str
- city:
- description:
- - Configures the user's city.
- type: str
- state_province:
- description:
- - Configures the user's state or province.
- type: str
- postal_code:
- description:
- - Configures the user's postal code / zip code.
- type: str
- country:
- description:
- - Configures the user's country code.
- - Note that this is a two-character ISO 3166 code.
- type: str
- path:
- description:
- - Container or OU for the new user; if you do not specify this, the
- user will be placed in the default container for users in the domain.
- - Setting the path is only available when a new user is created;
- if you specify a path on an existing user, the user's path will not
- be updated - you must delete (e.g., C(state=absent)) the user and
- then re-add the user with the appropriate path.
- type: str
- attributes:
- description:
- - A dict of custom LDAP attributes to set on the user.
- - This can be used to set custom attributes that are not exposed as module
- parameters, e.g. C(telephoneNumber).
- - See the examples on how to format this parameter.
- type: str
- version_added: '2.5'
- domain_username:
- description:
- - The username to use when interacting with AD.
- - If this is not set then the user Ansible used to log in with will be
- used instead when using CredSSP or Kerberos with credential delegation.
- type: str
- version_added: '2.5'
- domain_password:
- description:
- - The password for I(username).
- type: str
- version_added: '2.5'
- domain_server:
- description:
- - Specifies the Active Directory Domain Services instance to connect to.
- - Can be in the form of an FQDN or NetBIOS name.
- - If not specified then the value is based on the domain of the computer
- running PowerShell.
- type: str
- version_added: '2.5'
-notes:
- - Works with Windows 2012R2 and newer.
- - If running on a server that is not a Domain Controller, credential
- delegation through CredSSP or Kerberos with delegation must be used or the
- I(domain_username), I(domain_password) must be set.
- - Note that some individuals have confirmed successful operation on Windows
- 2008R2 servers with AD and AD Web Services enabled, but this has not
- received the same degree of testing as Windows 2012R2.
-seealso:
-- module: win_domain
-- module: win_domain_controller
-- module: win_domain_computer
-- module: win_domain_group
-- module: win_domain_membership
-- module: win_user
-- module: win_user_profile
-author:
- - Nick Chandler (@nwchandler)
-'''
-
-EXAMPLES = r'''
-- name: Ensure user bob is present with address information
- win_domain_user:
- name: bob
- firstname: Bob
- surname: Smith
- company: BobCo
- password: B0bP4ssw0rd
- state: present
- groups:
- - Domain Admins
- street: 123 4th St.
- city: Sometown
- state_province: IN
- postal_code: 12345
- country: US
- attributes:
- telephoneNumber: 555-123456
-
-- name: Ensure user bob is created and use custom credentials to create the user
- win_domain_user:
- name: bob
- firstname: Bob
- surname: Smith
- password: B0bP4ssw0rd
- state: present
- domain_username: DOMAIN\admin-account
- domain_password: SomePas2w0rd
- domain_server: domain@DOMAIN.COM
-
-- name: Ensure user bob is present in OU ou=test,dc=domain,dc=local
- win_domain_user:
- name: bob
- password: B0bP4ssw0rd
- state: present
- path: ou=test,dc=domain,dc=local
- groups:
- - Domain Admins
-
-- name: Ensure user bob is absent
- win_domain_user:
- name: bob
- state: absent
-'''
-
-RETURN = r'''
-account_locked:
- description: true if the account is locked
- returned: always
- type: bool
- sample: false
-changed:
- description: true if the account changed during execution
- returned: always
- type: bool
- sample: false
-city:
- description: The user city
- returned: always
- type: str
- sample: Indianapolis
-company:
- description: The user company
- returned: always
- type: str
- sample: RedHat
-country:
- description: The user country
- returned: always
- type: str
- sample: US
-description:
- description: A description of the account
- returned: always
- type: str
- sample: Server Administrator
-distinguished_name:
- description: DN of the user account
- returned: always
- type: str
- sample: CN=nick,OU=test,DC=domain,DC=local
-email:
- description: The user email address
- returned: always
- type: str
- sample: nick@domain.local
-enabled:
- description: true if the account is enabled and false if disabled
- returned: always
- type: str
- sample: true
-firstname:
- description: The user first name
- returned: always
- type: str
- sample: Nick
-groups:
- description: AD Groups to which the account belongs
- returned: always
- type: list
- sample: [ "Domain Admins", "Domain Users" ]
-msg:
- description: Summary message of whether the user is present or absent
- returned: always
- type: str
- sample: User nick is present
-name:
- description: The username on the account
- returned: always
- type: str
- sample: nick
-password_expired:
- description: true if the account password has expired
- returned: always
- type: bool
- sample: false
-password_updated:
- description: true if the password changed during this execution
- returned: always
- type: bool
- sample: true
-postal_code:
- description: The user postal code
- returned: always
- type: str
- sample: 46033
-sid:
- description: The SID of the account
- returned: always
- type: str
- sample: S-1-5-21-2752426336-228313920-2202711348-1175
-state:
- description: The state of the user account
- returned: always
- type: str
- sample: present
-state_province:
- description: The user state or province
- returned: always
- type: str
- sample: IN
-street:
- description: The user street address
- returned: always
- type: str
- sample: 123 4th St.
-surname:
- description: The user last name
- returned: always
- type: str
- sample: Doe
-upn:
- description: The User Principal Name of the account
- returned: always
- type: str
- sample: nick@domain.local
-user_cannot_change_password:
- description: true if the user is not allowed to change password
- returned: always
- type: str
- sample: false
-created:
- description: Whether a user was created
- returned: always
- type: bool
- sample: true
-'''
diff --git a/lib/ansible/modules/windows/win_dotnet_ngen.ps1 b/lib/ansible/modules/windows/win_dotnet_ngen.ps1
deleted file mode 100644
index 8dfca6b1ee..0000000000
--- a/lib/ansible/modules/windows/win_dotnet_ngen.ps1
+++ /dev/null
@@ -1,61 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Peter Mounce <public@neverrunwithscissors.com>
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-
-$ErrorActionPreference = 'Stop'
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$result = @{
- changed = $false
-}
-
-Function Invoke-Ngen($architecture="") {
- $cmd = "$($env:windir)\Microsoft.NET\Framework$($architecture)\v4.0.30319\ngen.exe"
-
- if (Test-Path -Path $cmd) {
- $arguments = "update /force"
- if ($check_mode) {
- $ngen_result = @{
- rc = 0
- stdout = "check mode output for $cmd $arguments"
- }
- } else {
- try {
- $ngen_result = Run-Command -command "$cmd $arguments"
- } catch {
- Fail-Json -obj $result -message "failed to execute '$cmd $arguments': $($_.Exception.Message)"
- }
- }
- $result."dotnet_ngen$($architecture)_update_exit_code" = $ngen_result.rc
- $result."dotnet_ngen$($architecture)_update_output" = $ngen_result.stdout
-
- $arguments = "executeQueuedItems"
- if ($check_mode) {
- $executed_queued_items = @{
- rc = 0
- stdout = "check mode output for $cmd $arguments"
- }
- } else {
- try {
- $executed_queued_items = Run-Command -command "$cmd $arguments"
- } catch {
- Fail-Json -obj $result -message "failed to execute '$cmd $arguments': $($_.Exception.Message)"
- }
- }
- $result."dotnet_ngen$($architecture)_eqi_exit_code" = $executed_queued_items.rc
- $result."dotnet_ngen$($architecture)_eqi_output" = $executed_queued_items.stdout
- $result.changed = $true
- }
-}
-
-Invoke-Ngen
-Invoke-Ngen -architecture "64"
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_dotnet_ngen.py b/lib/ansible/modules/windows/win_dotnet_ngen.py
deleted file mode 100644
index db682c98ec..0000000000
--- a/lib/ansible/modules/windows/win_dotnet_ngen.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Peter Mounce <public@neverrunwithscissors.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_dotnet_ngen
-version_added: "2.0"
-short_description: Runs ngen to recompile DLLs after .NET updates
-description:
- - After .NET framework is installed/updated, Windows will probably want to recompile things to optimise for the host.
- - This happens via scheduled task, usually at some inopportune time.
- - This module allows you to run this task on your own schedule, so you incur the CPU hit at some more convenient and controlled time.
- - U(https://docs.microsoft.com/en-us/dotnet/framework/tools/ngen-exe-native-image-generator#native-image-service)
- - U(http://blogs.msdn.com/b/dotnet/archive/2013/08/06/wondering-why-mscorsvw-exe-has-high-cpu-usage-you-can-speed-it-up.aspx)
-options: {}
-notes:
- - There are in fact two scheduled tasks for ngen but they have no triggers so aren't a problem.
- - There's no way to test if they've been completed.
- - The stdout is quite likely to be several megabytes.
-author:
-- Peter Mounce (@petemounce)
-'''
-
-EXAMPLES = r'''
-- name: Run ngen tasks
- win_dotnet_ngen:
-'''
-
-RETURN = r'''
-dotnet_ngen_update_exit_code:
- description: The exit code after running the 32-bit ngen.exe update /force
- command.
- returned: 32-bit ngen executable exists
- type: int
- sample: 0
-dotnet_ngen_update_output:
- description: The stdout after running the 32-bit ngen.exe update /force
- command.
- returned: 32-bit ngen executable exists
- type: str
- sample: sample output
-dotnet_ngen_eqi_exit_code:
- description: The exit code after running the 32-bit ngen.exe
- executeQueuedItems command.
- returned: 32-bit ngen executable exists
- type: int
- sample: 0
-dotnet_ngen_eqi_output:
- description: The stdout after running the 32-bit ngen.exe executeQueuedItems
- command.
- returned: 32-bit ngen executable exists
- type: str
- sample: sample output
-dotnet_ngen64_update_exit_code:
- description: The exit code after running the 64-bit ngen.exe update /force
- command.
- returned: 64-bit ngen executable exists
- type: int
- sample: 0
-dotnet_ngen64_update_output:
- description: The stdout after running the 64-bit ngen.exe update /force
- command.
- returned: 64-bit ngen executable exists
- type: str
- sample: sample output
-dotnet_ngen64_eqi_exit_code:
- description: The exit code after running the 64-bit ngen.exe
- executeQueuedItems command.
- returned: 64-bit ngen executable exists
- type: int
- sample: 0
-dotnet_ngen64_eqi_output:
- description: The stdout after running the 64-bit ngen.exe executeQueuedItems
- command.
- returned: 64-bit ngen executable exists
- type: str
- sample: sample output
-'''
diff --git a/lib/ansible/modules/windows/win_eventlog.ps1 b/lib/ansible/modules/windows/win_eventlog.ps1
deleted file mode 100644
index c4f695ce22..0000000000
--- a/lib/ansible/modules/windows/win_eventlog.ps1
+++ /dev/null
@@ -1,287 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Andrew Saraceni <andrew.saraceni@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$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
deleted file mode 100644
index 85cb948701..0000000000
--- a/lib/ansible/modules/windows/win_eventlog.py
+++ /dev/null
@@ -1,166 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Andrew Saraceni <andrew.saraceni@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- '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.
- type: str
- required: yes
- 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.
- type: str
- choices: [ absent, clear, present ]
- 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.
- type: list
- category_file:
- description:
- - For one or more sources specified, the path to a custom category resource file.
- type: path
- message_file:
- description:
- - For one or more sources specified, the path to a custom event message resource file.
- type: path
- parameter_file:
- description:
- - For one or more sources specified, the path to a custom parameter resource file.
- type: path
- 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).
- type: str
- overflow_action:
- description:
- - The action for the log to take once it reaches its maximum size.
- - For C(DoNotOverwrite), all existing entries are kept and new entries are not retained.
- - For C(OverwriteAsNeeded), each new entry overwrites the oldest entry.
- - For C(OverwriteOlder), new log entries overwrite those older than the C(retention_days) value.
- type: str
- choices: [ DoNotOverwrite, OverwriteAsNeeded, OverwriteOlder ]
- 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).
- type: int
-seealso:
-- module: win_eventlog_entry
-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: str
- sample: MyNewLog
-exists:
- description: Whether the event log exists or not.
- returned: success
- type: bool
- 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: str
- 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/lib/ansible/modules/windows/win_eventlog_entry.ps1 b/lib/ansible/modules/windows/win_eventlog_entry.ps1
deleted file mode 100644
index ddc4d1e168..0000000000
--- a/lib/ansible/modules/windows/win_eventlog_entry.ps1
+++ /dev/null
@@ -1,106 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Andrew Saraceni <andrew.saraceni@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-function Test-LogExistence {
- <#
- .SYNOPSIS
- Get information on a log's existence.
- #>
- param(
- [String]$LogName
- )
-
- $log_exists = $false
- $log = Get-EventLog -List | Where-Object {$_.Log -eq $LogName}
- if ($log) {
- $log_exists = $true
- }
- return $log_exists
-}
-
-function Test-SourceExistence {
- <#
- .SYNOPSIS
- Get information on a source's existence.
- #>
- param(
- [String]$LogName,
- [String]$SourceName
- )
-
- $source_exists = [System.Diagnostics.EventLog]::SourceExists($SourceName)
-
- if ($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 written to"
- }
- }
-
- return $source_exists
-}
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$log = Get-AnsibleParam -obj $params -name "log" -type "str" -failifempty $true
-$source = Get-AnsibleParam -obj $params -name "source" -type "str" -failifempty $true
-$event_id = Get-AnsibleParam -obj $params -name "event_id" -type "int" -failifempty $true
-$message = Get-AnsibleParam -obj $params -name "message" -type "str" -failifempty $true
-$entry_type = Get-AnsibleParam -obj $params -name "entry_type" -type "str" -validateset "Error","FailureAudit","Information","SuccessAudit","Warning"
-$category = Get-AnsibleParam -obj $params -name "category" -type "int"
-$raw_data = Get-AnsibleParam -obj $params -name "raw_data" -type "str"
-
-$result = @{
- changed = $false
-}
-
-$log_exists = Test-LogExistence -LogName $log
-if (!$log_exists) {
- Fail-Json -obj $result -message "Log $log does not exist and cannot be written to"
-}
-
-$source_exists = Test-SourceExistence -LogName $log -SourceName $source
-if (!$source_exists) {
- Fail-Json -obj $result -message "Source $source does not exist"
-}
-
-if ($event_id -lt 0 -or $event_id -gt 65535) {
- Fail-Json -obj $result -message "Event ID must be between 0 and 65535"
-}
-
-$write_params = @{
- LogName = $log
- Source = $source
- EventId = $event_id
- Message = $message
-}
-
-try {
- if ($entry_type) {
- $write_params.EntryType = $entry_type
- }
- if ($category) {
- $write_params.Category = $category
- }
- if ($raw_data) {
- $write_params.RawData = [Byte[]]($raw_data -split ",")
- }
-
- if (!$check_mode) {
- Write-EventLog @write_params
- }
- $result.changed = $true
- $result.msg = "Entry added to log $log from source $source"
-}
-catch {
- Fail-Json -obj $result -message $_.Exception.Message
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_eventlog_entry.py b/lib/ansible/modules/windows/win_eventlog_entry.py
deleted file mode 100644
index 05652e9df5..0000000000
--- a/lib/ansible/modules/windows/win_eventlog_entry.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Andrew Saraceni <andrew.saraceni@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_eventlog_entry
-version_added: "2.4"
-short_description: Write entries to Windows event logs
-description:
- - Write log entries to a given event log from a specified source.
-options:
- log:
- description:
- - Name of the event log to write an entry to.
- type: str
- required: yes
- source:
- description:
- - Name of the log source to indicate where the entry is from.
- type: str
- required: yes
- event_id:
- description:
- - The numeric event identifier for the entry.
- - Value must be between 0 and 65535.
- type: int
- required: yes
- message:
- description:
- - The message for the given log entry.
- type: str
- required: yes
- entry_type:
- description:
- - Indicates the entry being written to the log is of a specific type.
- type: str
- choices: [ Error, FailureAudit, Information, SuccessAudit, Warning ]
- category:
- description:
- - A numeric task category associated with the category message file for the log source.
- type: int
- raw_data:
- description:
- - Binary data associated with the log entry.
- - Value must be a comma-separated array of 8-bit unsigned integers (0 to 255).
- type: str
-notes:
- - This module will always report a change when writing an event entry.
-seealso:
-- module: win_eventlog
-author:
- - Andrew Saraceni (@andrewsaraceni)
-'''
-
-EXAMPLES = r'''
-- name: Write an entry to a Windows event log
- win_eventlog_entry:
- log: MyNewLog
- source: NewLogSource1
- event_id: 1234
- message: This is a test log entry.
-
-- name: Write another entry to a different Windows event log
- win_eventlog_entry:
- log: AnotherLog
- source: MyAppSource
- event_id: 5000
- message: An error has occurred.
- entry_type: Error
- category: 5
- raw_data: 10,20
-'''
-
-RETURN = r'''
-# Default return values
-'''
diff --git a/lib/ansible/modules/windows/win_file_compression.ps1 b/lib/ansible/modules/windows/win_file_compression.ps1
deleted file mode 100644
index 893cc50278..0000000000
--- a/lib/ansible/modules/windows/win_file_compression.ps1
+++ /dev/null
@@ -1,118 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Micah Hunsberger
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-Set-StrictMode -Version 2
-
-$spec = @{
- options = @{
- path = @{ type = 'path'; required = $true }
- state = @{ type = 'str'; default = 'present'; choices = 'absent', 'present' }
- recurse = @{ type = 'bool'; default = $false }
- force = @{ type = 'bool'; default = $true }
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$path = $module.Params.path
-$state = $module.Params.state
-$recurse = $module.Params.recurse
-$force = $module.Params.force
-
-$module.Result.rc = 0
-
-if(-not (Test-Path -LiteralPath $path)) {
- $module.FailJson("Path to item, $path, does not exist.")
-}
-
-$item = Get-Item -LiteralPath $path -Force # Use -Force for hidden files
-if (-not $item.PSIsContainer -and $recurse) {
- $module.Warn("The recurse option has no effect when path is not a folder.")
-}
-
-$cim_params = @{
- ClassName = 'Win32_LogicalDisk'
- Filter = "DeviceId='$($item.PSDrive.Name):'"
- Property = @('FileSystem', 'SupportsFileBasedCompression')
-}
-$drive_info = Get-CimInstance @cim_params
-if ($drive_info.SupportsFileBasedCompression -eq $false) {
- $module.FailJson("Path, $path, is not on a filesystemi '$($drive_info.FileSystem)' that supports file based compression.")
-}
-
-function Get-ReturnCodeMessage {
- param(
- [int]$code
- )
- switch ($code) {
- 0 { return "The request was successful." }
- 2 { return "Access was denied." }
- 8 { return "An unspecified failure occurred." }
- 9 { return "The name specified was not valid." }
- 10 { return "The object specified already exists." }
- 11 { return "The file system is not NTFS." }
- 12 { return "The platform is not Windows." }
- 13 { return "The drive is not the same." }
- 14 { return "The directory is not empty." }
- 15 { return "There has been a sharing violation." }
- 16 { return "The start file specified was not valid." }
- 17 { return "A privilege required for the operation is not held." }
- 21 { return "A parameter specified is not valid." }
- }
-}
-
-function Get-EscapedFileName {
- param(
- [string]$FullName
- )
- return $FullName.Replace("\","\\").Replace("'","\'")
-}
-
-$is_compressed = ($item.Attributes -band [System.IO.FileAttributes]::Compressed) -eq [System.IO.FileAttributes]::Compressed
-$needs_changed = $is_compressed -ne ($state -eq 'present')
-
-if($force -and $recurse -and $item.PSIsContainer) {
- if (-not $needs_changed) {
- # Check the subfolders and files
- $entries_to_check = $item.EnumerateFileSystemInfos("*", [System.IO.SearchOption]::AllDirectories)
- foreach ($entry in $entries_to_check) {
- $is_compressed = ($entry.Attributes -band [System.IO.FileAttributes]::Compressed) -eq [System.IO.FileAttributes]::Compressed
- if ($is_compressed -ne ($state -eq 'present')) {
- $needs_changed = $true
- break
- }
- }
- }
-}
-
-if($needs_changed) {
- $module.Result.changed = $true
- if ($item.PSIsContainer) {
- $cim_obj = Get-CimInstance -ClassName 'Win32_Directory' -Filter "Name='$(Get-EscapedFileName -FullName $item.FullName)'"
- } else {
- $cim_obj = Get-CimInstance -ClassName 'CIM_LogicalFile' -Filter "Name='$(Get-EscapedFileName -FullName $item.FullName)'"
- }
- if($state -eq 'present') {
- if(-not $module.CheckMode) {
- $ret = Invoke-CimMethod -InputObject $cim_obj -MethodName 'CompressEx' -Arguments @{ Recursive = $recurse }
- $module.Result.rc = $ret.ReturnValue
- }
- } else {
- if(-not $module.CheckMode) {
- $ret = $ret = Invoke-CimMethod -InputObject $cim_obj -MethodName 'UnCompressEx' -Arguments @{ Recursive = $recurse }
- $module.Result.rc = $ret.ReturnValue
- }
- }
-}
-
-$module.Result.msg = Get-ReturnCodeMessage -code $module.Result.rc
-if($module.Result.rc -ne 0) {
- $module.FailJson($module.Result.msg)
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_file_compression.py b/lib/ansible/modules/windows/win_file_compression.py
deleted file mode 100644
index 3bc59cade0..0000000000
--- a/lib/ansible/modules/windows/win_file_compression.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2019, Micah Hunsberger (@mhunsber)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_file_compression
-version_added: '2.10'
-short_description: Alters the compression of files and directories on NTFS partitions.
-description:
- - This module sets the compressed attribute for files and directories on a filesystem that supports it like NTFS.
- - NTFS compression can be used to save disk space.
-options:
- path:
- description:
- - The full path of the file or directory to modify.
- - The path must exist on file system that supports compression like NTFS.
- required: yes
- type: path
- state:
- description:
- - Set to C(present) to ensure the I(path) is compressed.
- - Set to C(absent) to ensure the I(path) is not compressed.
- type: str
- choices:
- - absent
- - present
- default: present
- recurse:
- description:
- - Whether to recursively apply changes to all subdirectories and files.
- - This option only has an effect when I(path) is a directory.
- - When set to C(false), only applies changes to I(path).
- - When set to C(true), applies changes to I(path) and all subdirectories and files.
- type: bool
- default: false
- force:
- description:
- - This option only has an effect when I(recurse) is C(true)
- - If C(true), will check the compressed state of all subdirectories and files
- and make a change if any are different from I(compressed).
- - If C(false), will only make a change if the compressed state of I(path) is different from I(compressed).
- - If the folder structure is complex or contains a lot of files, it is recommended to set this
- option to C(false) so that not every file has to be checked.
- type: bool
- default: true
-author:
- - Micah Hunsberger (@mhunsber)
-notes:
- - C(win_file_compression) sets the file system's compression state, it does not create a zip archive file.
- - For more about NTFS Compression, see U(http://www.ntfs.com/ntfs-compressed.htm)
-'''
-
-EXAMPLES = r'''
-- name: Compress log files directory
- win_file_compression:
- path: C:\Logs
- state: present
-
-- name: Decompress log files directory
- win_file_compression:
- path: C:\Logs
- state: absent
-
-- name: Compress reports directory and all subdirectories
- win_file_compression:
- path: C:\business\reports
- state: present
- recurse: yes
-
-# This will only check C:\business\reports for the compressed state
-# If C:\business\reports is compressed, it will not make a change
-# even if one of the child items is uncompressed
-
-- name: Compress reports directory and all subdirectories (quick)
- win_file_compression:
- path: C:\business\reports
- compressed: yes
- recurse: yes
- force: no
-'''
-
-RETURN = r'''
-rc:
- description:
- - The return code of the compress/uncompress operation.
- - If no changes are made or the operation is successful, rc is 0.
- returned: always
- sample: 0
- type: int
-'''
diff --git a/lib/ansible/modules/windows/win_file_version.ps1 b/lib/ansible/modules/windows/win_file_version.ps1
deleted file mode 100644
index 7fc6b557ef..0000000000
--- a/lib/ansible/modules/windows/win_file_version.ps1
+++ /dev/null
@@ -1,63 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Sam Liu <sam.liu@activenetwork.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$params = Parse-Args $args -supports_check_mode $true
-
-$result = @{
- win_file_version = @{}
- changed = $false
-}
-
-$path = Get-AnsibleParam -obj $params -name "path" -type "path" -failifempty $true -resultobj $result
-
-If (-Not (Test-Path -Path $path -PathType Leaf)){
- Fail-Json $result "Specified path $path does not exist or is not a file."
-}
-$ext = [System.IO.Path]::GetExtension($path)
-If ( $ext -notin '.exe', '.dll'){
- Fail-Json $result "Specified path $path is not a valid file type; must be DLL or EXE."
-}
-
-Try {
- $_version_fields = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($path)
- $file_version = $_version_fields.FileVersion
- If ($null -eq $file_version){
- $file_version = ''
- }
- $product_version = $_version_fields.ProductVersion
- If ($null -eq $product_version){
- $product_version= ''
- }
- $file_major_part = $_version_fields.FileMajorPart
- If ($null -eq $file_major_part){
- $file_major_part= ''
- }
- $file_minor_part = $_version_fields.FileMinorPart
- If ($null -eq $file_minor_part){
- $file_minor_part= ''
- }
- $file_build_part = $_version_fields.FileBuildPart
- If ($null -eq $file_build_part){
- $file_build_part = ''
- }
- $file_private_part = $_version_fields.FilePrivatePart
- If ($null -eq $file_private_part){
- $file_private_part = ''
- }
-}
-Catch{
- Fail-Json $result "Error: $_.Exception.Message"
-}
-
-$result.win_file_version.path = $path.toString()
-$result.win_file_version.file_version = $file_version.toString()
-$result.win_file_version.product_version = $product_version.toString()
-$result.win_file_version.file_major_part = $file_major_part.toString()
-$result.win_file_version.file_minor_part = $file_minor_part.toString()
-$result.win_file_version.file_build_part = $file_build_part.toString()
-$result.win_file_version.file_private_part = $file_private_part.toString()
-Exit-Json $result;
diff --git a/lib/ansible/modules/windows/win_file_version.py b/lib/ansible/modules/windows/win_file_version.py
deleted file mode 100644
index 390927821b..0000000000
--- a/lib/ansible/modules/windows/win_file_version.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Sam Liu <sam.liu@activenetwork.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_file_version
-version_added: "2.1"
-short_description: Get DLL or EXE file build version
-description:
- - Get DLL or EXE file build version.
-notes:
- - This module will always return no change.
-options:
- path:
- description:
- - File to get version.
- - Always provide absolute path.
- type: path
- required: yes
-seealso:
-- module: win_file
-author:
-- Sam Liu (@SamLiu79)
-'''
-
-EXAMPLES = r'''
-- name: Get acm instance version
- win_file_version:
- path: C:\Windows\System32\cmd.exe
- register: exe_file_version
-
-- debug:
- msg: '{{ exe_file_version }}'
-'''
-
-RETURN = r'''
-path:
- description: file path
- returned: always
- type: str
-
-file_version:
- description: File version number..
- returned: no error
- type: str
-
-product_version:
- description: The version of the product this file is distributed with.
- returned: no error
- type: str
-
-file_major_part:
- description: the major part of the version number.
- returned: no error
- type: str
-
-file_minor_part:
- description: the minor part of the version number of the file.
- returned: no error
- type: str
-
-file_build_part:
- description: build number of the file.
- returned: no error
- type: str
-
-file_private_part:
- description: file private part number.
- returned: no error
- type: str
-'''
diff --git a/lib/ansible/modules/windows/win_firewall.ps1 b/lib/ansible/modules/windows/win_firewall.ps1
deleted file mode 100644
index 2a628a3527..0000000000
--- a/lib/ansible/modules/windows/win_firewall.ps1
+++ /dev/null
@@ -1,68 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Michael Eaton <meaton@iforium.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-$firewall_profiles = @('Domain', 'Private', 'Public')
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$profiles = Get-AnsibleParam -obj $params -name "profiles" -type "list" -default @("Domain", "Private", "Public")
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -failifempty $true -validateset 'disabled','enabled'
-
-$result = @{
- changed = $false
- profiles = $profiles
- state = $state
-}
-
-try {
- get-command Get-NetFirewallProfile > $null
- get-command Set-NetFirewallProfile > $null
-}
-catch {
- Fail-Json $result "win_firewall requires Get-NetFirewallProfile and Set-NetFirewallProfile Cmdlets."
-}
-
-Try {
-
- ForEach ($profile in $firewall_profiles) {
-
- $currentstate = (Get-NetFirewallProfile -Name $profile).Enabled
- $result.$profile = @{
- enabled = ($currentstate -eq 1)
- considered = ($profiles -contains $profile)
- currentstate = $currentstate
- }
-
- if ($profiles -notcontains $profile) {
- continue
- }
-
- if ($state -eq 'enabled') {
-
- if ($currentstate -eq $false) {
- Set-NetFirewallProfile -name $profile -Enabled true -WhatIf:$check_mode
- $result.changed = $true
- $result.$profile.enabled = $true
- }
-
- } else {
-
- if ($currentstate -eq $true) {
- Set-NetFirewallProfile -name $profile -Enabled false -WhatIf:$check_mode
- $result.changed = $true
- $result.$profile.enabled = $false
- }
-
- }
- }
-} Catch {
- Fail-Json $result "an error occurred when attempting to change firewall status for profile $profile $($_.Exception.Message)"
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_firewall.py b/lib/ansible/modules/windows/win_firewall.py
deleted file mode 100644
index 62556b4901..0000000000
--- a/lib/ansible/modules/windows/win_firewall.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Michael Eaton <meaton@iforium.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_firewall
-version_added: '2.4'
-short_description: Enable or disable the Windows Firewall
-description:
-- Enable or Disable Windows Firewall profiles.
-requirements:
- - This module requires Windows Management Framework 5 or later.
-options:
- profiles:
- description:
- - Specify one or more profiles to change.
- type: list
- choices: [ Domain, Private, Public ]
- default: [ Domain, Private, Public ]
- state:
- description:
- - Set state of firewall for given profile.
- type: str
- choices: [ disabled, enabled ]
-seealso:
-- module: win_firewall_rule
-author:
-- Michael Eaton (@michaeldeaton)
-'''
-
-EXAMPLES = r'''
-- name: Enable firewall for Domain, Public and Private profiles
- win_firewall:
- state: enabled
- profiles:
- - Domain
- - Private
- - Public
- tags: enable_firewall
-
-- name: Disable Domain firewall
- win_firewall:
- state: disabled
- profiles:
- - Domain
- tags: disable_firewall
-'''
-
-RETURN = r'''
-enabled:
- description: Current firewall status for chosen profile (after any potential change).
- returned: always
- type: bool
- sample: true
-profiles:
- description: Chosen profile.
- returned: always
- type: str
- sample: Domain
-state:
- description: Desired state of the given firewall profile(s).
- returned: always
- type: list
- sample: enabled
-'''
diff --git a/lib/ansible/modules/windows/win_firewall_rule.ps1 b/lib/ansible/modules/windows/win_firewall_rule.ps1
deleted file mode 100644
index 3e6544eac4..0000000000
--- a/lib/ansible/modules/windows/win_firewall_rule.ps1
+++ /dev/null
@@ -1,257 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2014, Timothy Vandenbrande <timothy.vandenbrande@gmail.com>
-# Copyright: (c) 2017, Artem Zinenko <zinenkoartem@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-function Parse-ProtocolType {
- param($protocol)
-
- $protocolNumber = $protocol -as [int]
- if ($protocolNumber -is [int]) {
- return $protocolNumber
- }
-
- switch -wildcard ($protocol) {
- "tcp" { return [System.Net.Sockets.ProtocolType]::Tcp -as [int] }
- "udp" { return [System.Net.Sockets.ProtocolType]::Udp -as [int] }
- "icmpv4*" { return [System.Net.Sockets.ProtocolType]::Icmp -as [int] }
- "icmpv6*" { return [System.Net.Sockets.ProtocolType]::IcmpV6 -as [int] }
- default { throw "Unknown protocol '$protocol'." }
- }
-}
-
-# See 'Direction' constants here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364724(v=vs.85).aspx
-function Parse-Direction {
- param($directionStr)
-
- switch ($directionStr) {
- "in" { return 1 }
- "out" { return 2 }
- default { throw "Unknown direction '$directionStr'." }
- }
-}
-
-# See 'Action' constants here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364724(v=vs.85).aspx
-function Parse-Action {
- param($actionStr)
-
- switch ($actionStr) {
- "block" { return 0 }
- "allow" { return 1 }
- default { throw "Unknown action '$actionStr'." }
- }
-}
-
-# Profile enum values: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366303(v=vs.85).aspx
-function Parse-Profiles
-{
- param($profilesList)
-
- $profiles = ($profilesList | Select-Object -Unique | ForEach-Object {
- switch ($_) {
- "domain" { return 1 }
- "private" { return 2 }
- "public" { return 4 }
- default { throw "Unknown profile '$_'." }
- }
- } | Measure-Object -Sum).Sum
-
- if ($profiles -eq 7) { return 0x7fffffff }
- return $profiles
-}
-
-function Parse-InterfaceTypes
-{
- param($interfaceTypes)
-
- return ($interfaceTypes | Select-Object -Unique | ForEach-Object {
- switch ($_) {
- "wireless" { return "Wireless" }
- "lan" { return "Lan" }
- "ras" { return "RemoteAccess" }
- default { throw "Unknown interface type '$_'." }
- }
- }) -Join ","
-}
-
-function Parse-EdgeTraversalOptions
-{
- param($edgeTraversalOptionsStr)
-
- switch ($edgeTraversalOptionsStr) {
- "yes" { return 1 }
- "deferapp" { return 2 }
- "deferuser" { return 3 }
- default { throw "Unknown edge traversal options '$edgeTraversalOptionsStr'." }
- }
-}
-
-function Parse-SecureFlags
-{
- param($secureFlagsStr)
-
- switch ($secureFlagsStr) {
- "authnoencap" { return 1 }
- "authenticate" { return 2 }
- "authdynenc" { return 3 }
- "authenc" { return 4 }
- default { throw "Unknown secure flags '$secureFlagsStr'." }
- }
-}
-
-$ErrorActionPreference = "Stop"
-
-$result = @{
- changed = $false
-}
-
-$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
-
-$name = Get-AnsibleParam -obj $params -name "name" -failifempty $true
-$description = Get-AnsibleParam -obj $params -name "description" -type "str"
-$direction = Get-AnsibleParam -obj $params -name "direction" -type "str" -validateset "in","out"
-$action = Get-AnsibleParam -obj $params -name "action" -type "str" -validateset "allow","block"
-$program = Get-AnsibleParam -obj $params -name "program" -type "str"
-$group = Get-AnsibleParam -obj $params -name "group" -type "str"
-$service = Get-AnsibleParam -obj $params -name "service" -type "str"
-$enabled = Get-AnsibleParam -obj $params -name "enabled" -type "bool" -aliases "enable"
-$profiles = Get-AnsibleParam -obj $params -name "profiles" -type "list" -aliases "profile"
-$localip = Get-AnsibleParam -obj $params -name "localip" -type "str"
-$remoteip = Get-AnsibleParam -obj $params -name "remoteip" -type "str"
-$localport = Get-AnsibleParam -obj $params -name "localport" -type "str"
-$remoteport = Get-AnsibleParam -obj $params -name "remoteport" -type "str"
-$protocol = Get-AnsibleParam -obj $params -name "protocol" -type "str"
-$interfacetypes = Get-AnsibleParam -obj $params -name "interfacetypes" -type "list"
-$edge = Get-AnsibleParam -obj $params -name "edge" -type "str" -validateset "no","yes","deferapp","deferuser"
-$security = Get-AnsibleParam -obj $params -name "security" -type "str" -validateset "notrequired","authnoencap","authenticate","authdynenc","authenc"
-$icmp_type_code = Get-AnsibleParam -obj $params -name "icmp_type_code" -type "list"
-
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent"
-
-if ($diff_support) {
- $result.diff = @{}
- $result.diff.prepared = ""
-}
-
-if ($null -ne $icmp_type_code) {
- # COM representation is just "<type>:<code>,<type2>:<code>" so we just join our list
- $icmp_type_code = $icmp_type_code -join ","
-}
-
-try {
- $fw = New-Object -ComObject HNetCfg.FwPolicy2
-
- $existingRule = $fw.Rules | Where-Object { $_.Name -eq $name }
-
- if ($existingRule -is [System.Array]) {
- Fail-Json $result "Multiple firewall rules with name '$name' found."
- }
-
- # INetFwRule interface description: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365344(v=vs.85).aspx
- $new_rule = New-Object -ComObject HNetCfg.FWRule
- $new_rule.Name = $name
- # the default for enabled in module description is "true", but the actual COM object defaults to "false" when created
- if ($null -ne $enabled) { $new_rule.Enabled = $enabled } else { $new_rule.Enabled = $true }
- if ($null -ne $description) { $new_rule.Description = $description }
- if ($null -ne $group) { $new_rule.Grouping = $group }
- if ($null -ne $program -and $program -ne "any") { $new_rule.ApplicationName = [System.Environment]::ExpandEnvironmentVariables($program) }
- if ($null -ne $service -and $program -ne "any") { $new_rule.ServiceName = $service }
- if ($null -ne $protocol -and $protocol -ne "any") { $new_rule.Protocol = Parse-ProtocolType -protocol $protocol }
- if ($null -ne $localport -and $localport -ne "any") { $new_rule.LocalPorts = $localport }
- if ($null -ne $remoteport -and $remoteport -ne "any") { $new_rule.RemotePorts = $remoteport }
- if ($null -ne $localip -and $localip -ne "any") { $new_rule.LocalAddresses = $localip }
- if ($null -ne $remoteip -and $remoteip -ne "any") { $new_rule.RemoteAddresses = $remoteip }
- if ($null -ne $icmp_type_code -and $icmp_type_code -ne "any") { $new_rule.IcmpTypesAndCodes = $icmp_type_code }
- if ($null -ne $direction) { $new_rule.Direction = Parse-Direction -directionStr $direction }
- if ($null -ne $action) { $new_rule.Action = Parse-Action -actionStr $action }
- # Profiles value cannot be a uint32, but the "all profiles" value (0x7FFFFFFF) will often become a uint32, so must cast to [int]
- if ($null -ne $profiles) { $new_rule.Profiles = [int](Parse-Profiles -profilesList $profiles) }
- if ($null -ne $interfacetypes -and @(Compare-Object -ReferenceObject $interfacetypes -DifferenceObject @("any")).Count -ne 0) { $new_rule.InterfaceTypes = Parse-InterfaceTypes -interfaceTypes $interfacetypes }
- if ($null -ne $edge -and $edge -ne "no") {
- # EdgeTraversalOptions property exists only from Windows 7/Windows Server 2008 R2: https://msdn.microsoft.com/en-us/library/windows/desktop/dd607256(v=vs.85).aspx
- if ($new_rule | Get-Member -Name 'EdgeTraversalOptions') {
- $new_rule.EdgeTraversalOptions = Parse-EdgeTraversalOptions -edgeTraversalOptionsStr $edge
- }
- }
- if ($null -ne $security -and $security -ne "notrequired") {
- # SecureFlags property exists only from Windows 8/Windows Server 2012: https://msdn.microsoft.com/en-us/library/windows/desktop/hh447465(v=vs.85).aspx
- if ($new_rule | Get-Member -Name 'SecureFlags') {
- $new_rule.SecureFlags = Parse-SecureFlags -secureFlagsStr $security
- }
- }
-
- $fwPropertiesToCompare = @('Name','Description','Direction','Action','ApplicationName','Grouping','ServiceName','Enabled','Profiles','LocalAddresses','RemoteAddresses','LocalPorts','RemotePorts','Protocol','InterfaceTypes', 'EdgeTraversalOptions', 'SecureFlags','IcmpTypesAndCodes')
- $userPassedArguments = @($name, $description, $direction, $action, $program, $group, $service, $enabled, $profiles, $localip, $remoteip, $localport, $remoteport, $protocol, $interfacetypes, $edge, $security, $icmp_type_code)
-
- if ($state -eq "absent") {
- if ($null -eq $existingRule) {
- $result.msg = "Firewall rule '$name' does not exist."
- } else {
- if ($diff_support) {
- foreach ($prop in $fwPropertiesToCompare) {
- $result.diff.prepared += "-[$($prop)='$($existingRule.$prop)']`n"
- }
- }
-
- if (-not $check_mode) {
- $fw.Rules.Remove($existingRule.Name)
- }
- $result.changed = $true
- $result.msg = "Firewall rule '$name' removed."
- }
- } elseif ($state -eq "present") {
- if ($null -eq $existingRule) {
- if ($diff_support) {
- foreach ($prop in $fwPropertiesToCompare) {
- $result.diff.prepared += "+[$($prop)='$($new_rule.$prop)']`n"
- }
- }
-
- if (-not $check_mode) {
- $fw.Rules.Add($new_rule)
- }
- $result.changed = $true
- $result.msg = "Firewall rule '$name' created."
- } else {
- for($i = 0; $i -lt $fwPropertiesToCompare.Length; $i++) {
- $prop = $fwPropertiesToCompare[$i]
- if($null -ne $userPassedArguments[$i]) { # only change values the user passes in task definition
- if ($existingRule.$prop -ne $new_rule.$prop) {
- if ($diff_support) {
- $result.diff.prepared += "-[$($prop)='$($existingRule.$prop)']`n"
- $result.diff.prepared += "+[$($prop)='$($new_rule.$prop)']`n"
- }
-
- if (-not $check_mode) {
- # Profiles value cannot be a uint32, but the "all profiles" value (0x7FFFFFFF) will often become a uint32, so must cast to [int]
- # to prevent InvalidCastException under PS5+
- If($prop -eq 'Profiles') {
- $existingRule.Profiles = [int] $new_rule.$prop
- }
- Else {
- $existingRule.$prop = $new_rule.$prop
- }
- }
- $result.changed = $true
- }
- }
- }
- if ($result.changed) {
- $result.msg = "Firewall rule '$name' changed."
- } else {
- $result.msg = "Firewall rule '$name' already exists."
- }
- }
- }
-} catch [Exception] {
- $ex = $_
- $result['exception'] = $($ex | Out-String)
- Fail-Json $result $ex.Exception.Message
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_firewall_rule.py b/lib/ansible/modules/windows/win_firewall_rule.py
deleted file mode 100644
index d25468d362..0000000000
--- a/lib/ansible/modules/windows/win_firewall_rule.py
+++ /dev/null
@@ -1,192 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2014, Timothy Vandenbrande <timothy.vandenbrande@gmail.com>
-# Copyright: (c) 2017, Artem Zinenko <zinenkoartem@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_firewall_rule
-version_added: "2.0"
-short_description: Windows firewall automation
-description:
- - Allows you to create/remove/update firewall rules.
-options:
- enabled:
- description:
- - Whether this firewall rule is enabled or disabled.
- - Defaults to C(true) when creating a new rule.
- type: bool
- aliases: [ enable ]
- state:
- description:
- - Should this rule be added or removed.
- type: str
- choices: [ absent, present ]
- default: present
- name:
- description:
- - The rule's display name.
- type: str
- required: yes
- group:
- description:
- - The group name for the rule.
- version_added: '2.9'
- type: str
- direction:
- description:
- - Whether this rule is for inbound or outbound traffic.
- - Defaults to C(in) when creating a new rule.
- type: str
- choices: [ in, out ]
- action:
- description:
- - What to do with the items this rule is for.
- - Defaults to C(allow) when creating a new rule.
- type: str
- choices: [ allow, block ]
- description:
- description:
- - Description for the firewall rule.
- type: str
- localip:
- description:
- - The local ip address this rule applies to.
- - Set to C(any) to apply to all local ip addresses.
- - Defaults to C(any) when creating a new rule.
- type: str
- remoteip:
- description:
- - The remote ip address/range this rule applies to.
- - Set to C(any) to apply to all remote ip addresses.
- - Defaults to C(any) when creating a new rule.
- type: str
- localport:
- description:
- - The local port this rule applies to.
- - Set to C(any) to apply to all local ports.
- - Defaults to C(any) when creating a new rule.
- - Must have I(protocol) set
- type: str
- remoteport:
- description:
- - The remote port this rule applies to.
- - Set to C(any) to apply to all remote ports.
- - Defaults to C(any) when creating a new rule.
- - Must have I(protocol) set
- type: str
- program:
- description:
- - The program this rule applies to.
- - Set to C(any) to apply to all programs.
- - Defaults to C(any) when creating a new rule.
- type: str
- service:
- description:
- - The service this rule applies to.
- - Set to C(any) to apply to all services.
- - Defaults to C(any) when creating a new rule.
- type: str
- protocol:
- description:
- - The protocol this rule applies to.
- - Set to C(any) to apply to all services.
- - Defaults to C(any) when creating a new rule.
- type: str
- profiles:
- description:
- - The profile this rule applies to.
- - Defaults to C(domain,private,public) when creating a new rule.
- type: list
- aliases: [ profile ]
- icmp_type_code:
- description:
- - The ICMP types and codes for the rule.
- - This is only valid when I(protocol) is C(icmpv4) or C(icmpv6).
- - Each entry follows the format C(type:code) where C(type) is the type
- number and C(code) is the code number for that type or C(*) for all
- codes.
- - Set the value to just C(*) to apply the rule for all ICMP type codes.
- - See U(https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml)
- for a list of ICMP types and the codes that apply to them.
- type: list
- version_added: '2.10'
-seealso:
-- module: win_firewall
-author:
- - Artem Zinenko (@ar7z1)
- - Timothy Vandenbrande (@TimothyVandenbrande)
-'''
-
-EXAMPLES = r'''
-- name: Firewall rule to allow SMTP on TCP port 25
- win_firewall_rule:
- name: SMTP
- localport: 25
- action: allow
- direction: in
- protocol: tcp
- state: present
- enabled: yes
-
-- name: Firewall rule to allow RDP on TCP port 3389
- win_firewall_rule:
- name: Remote Desktop
- localport: 3389
- action: allow
- direction: in
- protocol: tcp
- profiles: private
- state: present
- enabled: yes
-
-- name: Firewall rule to be created for application group
- win_firewall_rule:
- name: SMTP
- group: application
- localport: 25
- action: allow
- direction: in
- protocol: tcp
- state: present
- enabled: yes
-
-- name: Firewall rule to allow port range
- win_firewall_rule:
- name: Sample port range
- localport: 5000-5010
- action: allow
- direction: in
- protocol: tcp
- state: present
- enabled: yes
-
-- name: Firewall rule to allow ICMP v4 echo (ping)
- win_firewall_rule:
- name: ICMP Allow incoming V4 echo request
- enabled: yes
- state: present
- profiles: private
- action: allow
- direction: in
- protocol: icmpv4
- icmp_type_code:
- - '8:*'
-
-- name: Firewall rule to alloc ICMP v4 on all type codes
- win_firewall_rule:
- name: ICMP Allow incoming V4 echo request
- enabled: yes
- state: present
- profiles: private
- action: allow
- direction: in
- protocol: icmpv4
- icmp_type_code: '*'
-'''
diff --git a/lib/ansible/modules/windows/win_format.ps1 b/lib/ansible/modules/windows/win_format.ps1
deleted file mode 100644
index b5fd3ae038..0000000000
--- a/lib/ansible/modules/windows/win_format.ps1
+++ /dev/null
@@ -1,200 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Varun Chopra (@chopraaa) <v@chopraaa.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#AnsibleRequires -OSVersion 6.2
-
-Set-StrictMode -Version 2
-
-$ErrorActionPreference = "Stop"
-
-$spec = @{
- options = @{
- drive_letter = @{ type = "str" }
- path = @{ type = "str" }
- label = @{ type = "str" }
- new_label = @{ type = "str" }
- file_system = @{ type = "str"; choices = "ntfs", "refs", "exfat", "fat32", "fat" }
- allocation_unit_size = @{ type = "int" }
- large_frs = @{ type = "bool" }
- full = @{ type = "bool"; default = $false }
- compress = @{ type = "bool" }
- integrity_streams = @{ type = "bool" }
- force = @{ type = "bool"; default = $false }
- }
- mutually_exclusive = @(
- ,@('drive_letter', 'path', 'label')
- )
- required_one_of = @(
- ,@('drive_letter', 'path', 'label')
- )
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$drive_letter = $module.Params.drive_letter
-$path = $module.Params.path
-$label = $module.Params.label
-$new_label = $module.Params.new_label
-$file_system = $module.Params.file_system
-$allocation_unit_size = $module.Params.allocation_unit_size
-$large_frs = $module.Params.large_frs
-$full_format = $module.Params.full
-$compress_volume = $module.Params.compress
-$integrity_streams = $module.Params.integrity_streams
-$force_format = $module.Params.force
-
-# Some pre-checks
-if ($null -ne $drive_letter -and $drive_letter -notmatch "^[a-zA-Z]$") {
- $module.FailJson("The parameter drive_letter should be a single character A-Z")
-}
-if ($integrity_streams -eq $true -and $file_system -ne "refs") {
- $module.FailJson("Integrity streams can be enabled only on ReFS volumes. You specified: $($file_system)")
-}
-if ($compress_volume -eq $true) {
- if ($file_system -eq "ntfs") {
- if ($null -ne $allocation_unit_size -and $allocation_unit_size -gt 4096) {
- $module.FailJson("NTFS compression is not supported for allocation unit sizes above 4096")
- }
- }
- else {
- $module.FailJson("Compression can be enabled only on NTFS volumes. You specified: $($file_system)")
- }
-}
-
-function Get-AnsibleVolume {
- param(
- $DriveLetter,
- $Path,
- $Label
- )
-
- if ($null -ne $DriveLetter) {
- try {
- $volume = Get-Volume -DriveLetter $DriveLetter
- } catch {
- $module.FailJson("There was an error retrieving the volume using drive_letter $($DriveLetter): $($_.Exception.Message)", $_)
- }
- }
- elseif ($null -ne $Path) {
- try {
- $volume = Get-Volume -Path $Path
- } catch {
- $module.FailJson("There was an error retrieving the volume using path $($Path): $($_.Exception.Message)", $_)
- }
- }
- elseif ($null -ne $Label) {
- try {
- $volume = Get-Volume -FileSystemLabel $Label
- } catch {
- $module.FailJson("There was an error retrieving the volume using label $($Label): $($_.Exception.Message)", $_)
- }
- }
- else {
- $module.FailJson("Unable to locate volume: drive_letter, path and label were not specified")
- }
-
- return $volume
-}
-
-function Format-AnsibleVolume {
- param(
- $Path,
- $Label,
- $FileSystem,
- $Full,
- $UseLargeFRS,
- $Compress,
- $SetIntegrityStreams,
- $AllocationUnitSize
- )
- $parameters = @{
- Path = $Path
- Full = $Full
- }
- if ($null -ne $UseLargeFRS) {
- $parameters.Add("UseLargeFRS", $UseLargeFRS)
- }
- if ($null -ne $SetIntegrityStreams) {
- $parameters.Add("SetIntegrityStreams", $SetIntegrityStreams)
- }
- if ($null -ne $Compress){
- $parameters.Add("Compress", $Compress)
- }
- if ($null -ne $Label) {
- $parameters.Add("NewFileSystemLabel", $Label)
- }
- if ($null -ne $FileSystem) {
- $parameters.Add("FileSystem", $FileSystem)
- }
- if ($null -ne $AllocationUnitSize) {
- $parameters.Add("AllocationUnitSize", $AllocationUnitSize)
- }
-
- Format-Volume @parameters -Confirm:$false | Out-Null
-
-}
-
-$ansible_volume = Get-AnsibleVolume -DriveLetter $drive_letter -Path $path -Label $label
-$ansible_file_system = $ansible_volume.FileSystem
-$ansible_volume_size = $ansible_volume.Size
-$ansible_volume_alu = (Get-CimInstance -ClassName Win32_Volume -Filter "DeviceId = '$($ansible_volume.path.replace('\','\\'))'" -Property BlockSize).BlockSize
-
-$ansible_partition = Get-Partition -Volume $ansible_volume
-
-if (-not $force_format -and $null -ne $allocation_unit_size -and $ansible_volume_alu -ne 0 -and $null -ne $ansible_volume_alu -and $allocation_unit_size -ne $ansible_volume_alu) {
- $module.FailJson("Force format must be specified since target allocation unit size: $($allocation_unit_size) is different from the current allocation unit size of the volume: $($ansible_volume_alu)")
-}
-
-foreach ($access_path in $ansible_partition.AccessPaths) {
- if ($access_path -ne $Path) {
- if ($null -ne $file_system -and
- -not [string]::IsNullOrEmpty($ansible_file_system) -and
- $file_system -ne $ansible_file_system)
- {
- if (-not $force_format)
- {
- $no_files_in_volume = (Get-ChildItem -LiteralPath $access_path -ErrorAction SilentlyContinue | Measure-Object).Count -eq 0
- if($no_files_in_volume)
- {
- $module.FailJson("Force format must be specified since target file system: $($file_system) is different from the current file system of the volume: $($ansible_file_system.ToLower())")
- }
- else
- {
- $module.FailJson("Force format must be specified to format non-pristine volumes")
- }
- }
- }
- else
- {
- $pristine = -not $force_format
- }
- }
-}
-
-if ($force_format) {
- if (-not $module.CheckMode) {
- Format-AnsibleVolume -Path $ansible_volume.Path -Full $full_format -Label $new_label -FileSystem $file_system -SetIntegrityStreams $integrity_streams -UseLargeFRS $large_frs -Compress $compress_volume -AllocationUnitSize $allocation_unit_size
- }
- $module.Result.changed = $true
-}
-else {
- if ($pristine) {
- if ($null -eq $new_label) {
- $new_label = $ansible_volume.FileSystemLabel
- }
- # Conditions for formatting
- if ($ansible_volume_size -eq 0 -or
- $ansible_volume.FileSystemLabel -ne $new_label) {
- if (-not $module.CheckMode) {
- Format-AnsibleVolume -Path $ansible_volume.Path -Full $full_format -Label $new_label -FileSystem $file_system -SetIntegrityStreams $integrity_streams -UseLargeFRS $large_frs -Compress $compress_volume -AllocationUnitSize $allocation_unit_size
- }
- $module.Result.changed = $true
- }
- }
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_format.py b/lib/ansible/modules/windows/win_format.py
deleted file mode 100644
index f8f18ed7b7..0000000000
--- a/lib/ansible/modules/windows/win_format.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2019, Varun Chopra (@chopraaa) <v@chopraaa.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = r'''
-module: win_format
-version_added: '2.8'
-short_description: Formats an existing volume or a new volume on an existing partition on Windows
-description:
- - The M(win_format) module formats an existing volume or a new volume on an existing partition on Windows
-options:
- drive_letter:
- description:
- - Used to specify the drive letter of the volume to be formatted.
- type: str
- path:
- description:
- - Used to specify the path to the volume to be formatted.
- type: str
- label:
- description:
- - Used to specify the label of the volume to be formatted.
- type: str
- new_label:
- description:
- - Used to specify the new file system label of the formatted volume.
- type: str
- file_system:
- description:
- - Used to specify the file system to be used when formatting the target volume.
- type: str
- choices: [ ntfs, refs, exfat, fat32, fat ]
- allocation_unit_size:
- description:
- - Specifies the cluster size to use when formatting the volume.
- - If no cluster size is specified when you format a partition, defaults are selected based on
- the size of the partition.
- - This value must be a multiple of the physical sector size of the disk.
- type: int
- large_frs:
- description:
- - Specifies that large File Record System (FRS) should be used.
- type: bool
- compress:
- description:
- - Enable compression on the resulting NTFS volume.
- - NTFS compression is not supported where I(allocation_unit_size) is more than 4096.
- type: bool
- integrity_streams:
- description:
- - Enable integrity streams on the resulting ReFS volume.
- type: bool
- full:
- description:
- - A full format writes to every sector of the disk, takes much longer to perform than the
- default (quick) format, and is not recommended on storage that is thinly provisioned.
- - Specify C(true) for full format.
- type: bool
- force:
- description:
- - Specify if formatting should be forced for volumes that are not created from new partitions
- or if the source and target file system are different.
- type: bool
-notes:
- - Microsoft Windows Server 2012 or Microsoft Windows 8 or newer is required to use this module. To check if your system is compatible, see
- U(https://docs.microsoft.com/en-us/windows/desktop/sysinfo/operating-system-version).
- - One of three parameters (I(drive_letter), I(path) and I(label)) are mandatory to identify the target
- volume but more than one cannot be specified at the same time.
- - This module is idempotent if I(force) is not specified and file system labels remain preserved.
- - For more information, see U(https://docs.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/format-msft-volume)
-seealso:
- - module: win_disk_facts
- - module: win_partition
-author:
- - Varun Chopra (@chopraaa) <v@chopraaa.com>
-'''
-
-EXAMPLES = r'''
-- name: Create a partition with drive letter D and size 5 GiB
- win_partition:
- drive_letter: D
- partition_size: 5 GiB
- disk_number: 1
-
-- name: Full format the newly created partition as NTFS and label it
- win_format:
- drive_letter: D
- file_system: NTFS
- new_label: Formatted
- full: True
-'''
-
-RETURN = r'''
-#
-'''
diff --git a/lib/ansible/modules/windows/win_hosts.ps1 b/lib/ansible/modules/windows/win_hosts.ps1
deleted file mode 100644
index 9e617c6664..0000000000
--- a/lib/ansible/modules/windows/win_hosts.ps1
+++ /dev/null
@@ -1,257 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Micah Hunsberger (@mhunsber)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-Set-StrictMode -Version 2
-$ErrorActionPreference = "Stop"
-
-$spec = @{
- options = @{
- state = @{ type = "str"; choices = "absent", "present"; default = "present" }
- aliases = @{ type = "list"; elements = "str" }
- canonical_name = @{ type = "str" }
- ip_address = @{ type = "str" }
- action = @{ type = "str"; choices = "add", "remove", "set"; default = "set" }
- }
- required_if = @(,@( "state", "present", @("canonical_name", "ip_address")))
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$state = $module.Params.state
-$aliases = $module.Params.aliases
-$canonical_name = $module.Params.canonical_name
-$ip_address = $module.Params.ip_address
-$action = $module.Params.action
-
-$tmp = [ipaddress]::None
-if($ip_address -and -not [ipaddress]::TryParse($ip_address, [ref]$tmp)){
- $module.FailJson("win_hosts: Argument ip_address needs to be a valid ip address, but was $ip_address")
-}
-$ip_address_type = $tmp.AddressFamily
-
-$hosts_file = Get-Item -LiteralPath "$env:SystemRoot\System32\drivers\etc\hosts"
-
-Function Get-CommentIndex($line) {
- $c_index = $line.IndexOf('#')
- if($c_index -lt 0) {
- $c_index = $line.Length
- }
- return $c_index
-}
-
-Function Get-HostEntryParts($line) {
- $success = $true
- $c_index = Get-CommentIndex -line $line
- $pure_line = $line.Substring(0,$c_index).Trim()
- $bits = $pure_line -split "\s+"
- if($bits.Length -lt 2){
- return @{
- success = $false
- ip_address = ""
- ip_type = ""
- canonical_name = ""
- aliases = @()
- }
- }
- $ip_obj = [ipaddress]::None
- if(-not [ipaddress]::TryParse($bits[0], [ref]$ip_obj) ){
- $success = $false
- }
- $cname = $bits[1]
- $als = New-Object string[] ($bits.Length - 2)
- [array]::Copy($bits, 2, $als, 0, $als.Length)
- return @{
- success = $success
- ip_address = $ip_obj.IPAddressToString
- ip_type = $ip_obj.AddressFamily
- canonical_name = $cname
- aliases = $als
- }
-}
-
-Function Find-HostName($line, $name) {
- $c_idx = Get-CommentIndex -line $line
- $re = New-Object regex ("\s+$($name.Replace('.',"\."))(\s|$)", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
- $match = $re.Match($line, 0, $c_idx)
- return $match
-}
-
-Function Remove-HostEntry($list, $idx) {
- $module.Result.changed = $true
- $list.RemoveAt($idx)
-}
-
-Function Add-HostEntry($list, $cname, $aliases, $ip) {
- $module.Result.changed = $true
- $line = "$ip $cname $($aliases -join ' ')"
- $list.Add($line) | Out-Null
-}
-
-Function Remove-HostnamesFromEntry($list, $idx, $aliases) {
- $line = $list[$idx]
- $line_removed = $false
-
- foreach($name in $aliases){
- $match = Find-HostName -line $line -name $name
- if($match.Success){
- $line = $line.Remove($match.Index + 1, $match.Length -1)
- # was this the last alias? (check for space characters after trimming)
- if($line.Substring(0,(Get-CommentIndex -line $line)).Trim() -inotmatch "\s") {
- $list.RemoveAt($idx)
- $line_removed = $true
- # we're done
- return @{
- line_removed = $line_removed
- }
- }
- }
- }
- if($line -ne $list[$idx]){
- $module.Result.changed = $true
- $list[$idx] = $line
- }
- return @{
- line_removed = $line_removed
- }
-}
-
-Function Add-AliasesToEntry($list, $idx, $aliases) {
- $line = $list[$idx]
- foreach($name in $aliases){
- $match = Find-HostName -line $line -name $name
- if(-not $match.Success) {
- # just add the alias before the comment
- $line = $line.Insert((Get-CommentIndex -line $line), " $name ")
- }
- }
- if($line -ne $list[$idx]){
- $module.Result.changed = $true
- $list[$idx] = $line
- }
-}
-
-$hosts_lines = New-Object System.Collections.ArrayList
-
-Get-Content -LiteralPath $hosts_file.FullName | ForEach-Object { $hosts_lines.Add($_) } | Out-Null
-$module.Diff.before = ($hosts_lines -join "`n") + "`n"
-
-if ($state -eq 'absent') {
- # go through and remove canonical_name and ip
- for($idx = 0; $idx -lt $hosts_lines.Count; $idx++) {
- $entry = $hosts_lines[$idx]
- # skip comment lines
- if(-not $entry.Trim().StartsWith('#')) {
- $entry_parts = Get-HostEntryParts -line $entry
- if($entry_parts.success) {
- if(-not $ip_address -or $entry_parts.ip_address -eq $ip_address) {
- if(-not $canonical_name -or $entry_parts.canonical_name -eq $canonical_name) {
- if(Remove-HostEntry -list $hosts_lines -idx $idx){
- # keep index correct if we removed the line
- $idx = $idx - 1
- }
- }
- }
- }
- }
- }
-}
-if($state -eq 'present') {
- $entry_idx = -1
- $aliases_to_keep = @()
- # go through lines, find the entry and determine what to remove based on action
- for($idx = 0; $idx -lt $hosts_lines.Count; $idx++) {
- $entry = $hosts_lines[$idx]
- # skip comment lines
- if(-not $entry.Trim().StartsWith('#')) {
- $entry_parts = Get-HostEntryParts -line $entry
- if($entry_parts.success) {
- $aliases_to_remove = @()
- if($entry_parts.ip_address -eq $ip_address) {
- if($entry_parts.canonical_name -eq $canonical_name) {
- $entry_idx = $idx
-
- if($action -eq 'set') {
- $aliases_to_remove = $entry_parts.aliases | Where-Object { $aliases -notcontains $_ }
- } elseif($action -eq 'remove') {
- $aliases_to_remove = $aliases
- }
- } else {
- # this is the right ip_address, but not the cname we were looking for.
- # we need to make sure none of aliases or canonical_name exist for this entry
- # since the given canonical_name should be an A/AAAA record,
- # and aliases should be cname records for the canonical_name.
- $aliases_to_remove = $aliases + $canonical_name
- }
- } else {
- # this is not the ip_address we are looking for
- if ($ip_address_type -eq $entry_parts.ip_type) {
- if ($entry_parts.canonical_name -eq $canonical_name) {
- Remove-HostEntry -list $hosts_lines -idx $idx
- $idx = $idx - 1
- if ($action -ne "set") {
- # keep old aliases intact
- $aliases_to_keep += $entry_parts.aliases | Where-Object { ($aliases + $aliases_to_keep + $canonical_name) -notcontains $_ }
- }
- } elseif ($action -eq "remove") {
- $aliases_to_remove = $canonical_name
- } elseif ($aliases -contains $entry_parts.canonical_name) {
- Remove-HostEntry -list $hosts_lines -idx $idx
- $idx = $idx - 1
- if ($action -eq "add") {
- # keep old aliases intact
- $aliases_to_keep += $entry_parts.aliases | Where-Object { ($aliases + $aliases_to_keep + $canonical_name) -notcontains $_ }
- }
- } else {
- $aliases_to_remove = $aliases + $canonical_name
- }
- } else {
- # TODO: Better ipv6 support. There is odd behavior for when an alias can be used for both ipv6 and ipv4
- }
- }
-
- if($aliases_to_remove) {
- if((Remove-HostnamesFromEntry -list $hosts_lines -idx $idx -aliases $aliases_to_remove).line_removed) {
- $idx = $idx - 1
- }
- }
- }
- }
- }
-
- if($entry_idx -ge 0) {
- $aliases_to_add = @()
- $entry_parts = Get-HostEntryParts -line $hosts_lines[$entry_idx]
- if($action -eq 'remove') {
- $aliases_to_add = $aliases_to_keep | Where-Object { $entry_parts.aliases -notcontains $_ }
- } else {
- $aliases_to_add = ($aliases + $aliases_to_keep) | Where-Object { $entry_parts.aliases -notcontains $_ }
- }
-
- if($aliases_to_add) {
- Add-AliasesToEntry -list $hosts_lines -idx $entry_idx -aliases $aliases_to_add
- }
- } else {
- # add the entry at the end
- if($action -eq 'remove') {
- if($aliases_to_keep) {
- Add-HostEntry -list $hosts_lines -ip $ip_address -cname $canonical_name -aliases $aliases_to_keep
- } else {
- Add-HostEntry -list $hosts_lines -ip $ip_address -cname $canonical_name
- }
- } else {
- Add-HostEntry -list $hosts_lines -ip $ip_address -cname $canonical_name -aliases ($aliases + $aliases_to_keep)
- }
- }
-}
-
-$module.Diff.after = ($hosts_lines -join "`n") + "`n"
-if( $module.Result.changed -and -not $module.CheckMode ) {
- Set-Content -LiteralPath $hosts_file.FullName -Value $hosts_lines
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_hosts.py b/lib/ansible/modules/windows/win_hosts.py
deleted file mode 100644
index 9fd2d1d10d..0000000000
--- a/lib/ansible/modules/windows/win_hosts.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Micah Hunsberger (@mhunsber)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_hosts
-version_added: '2.8'
-short_description: Manages hosts file entries on Windows.
-description:
- - Manages hosts file entries on Windows.
- - Maps IPv4 or IPv6 addresses to canonical names.
- - Adds, removes, or sets cname records for ip and hostname pairs.
- - Modifies %windir%\\system32\\drivers\\etc\\hosts.
-options:
- state:
- description:
- - Whether the entry should be present or absent.
- - If only I(canonical_name) is provided when C(state=absent), then
- all hosts entries with the canonical name of I(canonical_name)
- will be removed.
- - If only I(ip_address) is provided when C(state=absent), then all
- hosts entries with the ip address of I(ip_address) will be removed.
- - If I(ip_address) and I(canonical_name) are both omitted when
- C(state=absent), then all hosts entries will be removed.
- choices:
- - absent
- - present
- default: present
- type: str
- canonical_name:
- description:
- - A canonical name for the host entry.
- - required for C(state=present).
- type: str
- ip_address:
- description:
- - The ip address for the host entry.
- - Can be either IPv4 (A record) or IPv6 (AAAA record).
- - Required for C(state=present).
- type: str
- aliases:
- description:
- - A list of additional names (cname records) for the host entry.
- - Only applicable when C(state=present).
- type: list
- action:
- choices:
- - add
- - remove
- - set
- description:
- - Controls the behavior of I(aliases).
- - Only applicable when C(state=present).
- - If C(add), each alias in I(aliases) will be added to the host entry.
- - If C(set), each alias in I(aliases) will be added to the host entry,
- and other aliases will be removed from the entry.
- default: set
- type: str
-author:
- - Micah Hunsberger (@mhunsber)
-notes:
- - Each canonical name can only be mapped to one IPv4 and one IPv6 address.
- If I(canonical_name) is provided with C(state=present) and is found
- to be mapped to another IP address that is the same type as, but unique
- from I(ip_address), then I(canonical_name) and all I(aliases) will
- be removed from the entry and added to an entry with the provided IP address.
- - Each alias can only be mapped to one canonical name. If I(aliases) is provided
- with C(state=present) and an alias is found to be mapped to another canonical
- name, then the alias will be removed from the entry and either added to or removed
- from (depending on I(action)) an entry with the provided canonical name.
-seealso:
- - module: win_template
- - module: win_file
- - module: win_copy
-'''
-
-EXAMPLES = r'''
-- name: Add 127.0.0.1 as an A record for localhost
- win_hosts:
- state: present
- canonical_name: localhost
- ip_address: 127.0.0.1
-
-- name: Add ::1 as an AAAA record for localhost
- win_hosts:
- state: present
- canonical_name: localhost
- ip_address: '::1'
-
-- name: Remove 'bar' and 'zed' from the list of aliases for foo (192.168.1.100)
- win_hosts:
- state: present
- canoncial_name: foo
- ip_address: 192.168.1.100
- action: remove
- aliases:
- - bar
- - zed
-
-- name: Remove hosts entries with canonical name 'bar'
- win_hosts:
- state: absent
- canonical_name: bar
-
-- name: Remove 10.2.0.1 from the list of hosts
- win_hosts:
- state: absent
- ip_address: 10.2.0.1
-
-- name: Ensure all name resolution is handled by DNS
- win_hosts:
- state: absent
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_hotfix.ps1 b/lib/ansible/modules/windows/win_hotfix.ps1
deleted file mode 100644
index 1681763203..0000000000
--- a/lib/ansible/modules/windows/win_hotfix.ps1
+++ /dev/null
@@ -1,239 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$hotfix_kb = Get-AnsibleParam -obj $params -name "hotfix_kb" -type "str"
-$hotfix_identifier = Get-AnsibleParam -obj $params -name "hotfix_identifier" -type "str"
-$state = Get-AnsibleParam -obj $params -name "state" -type "state" -default "present" -validateset "absent","present"
-$source = Get-AnsibleParam -obj $params -name "source" -type "path"
-
-$result = @{
- changed = $false
- reboot_required = $false
-}
-
-if (Get-Module -Name DISM -ListAvailable) {
- Import-Module -Name DISM
-} else {
- # Server 2008 R2 doesn't have the DISM module installed on the path, check the Windows ADK path
- $adk_root = [System.Environment]::ExpandEnvironmentVariables("%PROGRAMFILES(X86)%\Windows Kits\*\Assessment and Deployment Kit\Deployment Tools\amd64\DISM")
- if (Test-Path -Path $adk_root) {
- Import-Module -Name (Get-Item -Path $adk_root).FullName
- } else {
- Fail-Json $result "The DISM PS module needs to be installed, this can be done through the windows-adk chocolately package"
- }
-}
-
-
-Function Extract-MSU($msu) {
- $temp_path = [IO.Path]::GetTempPath()
- $temp_foldername = [Guid]::NewGuid()
- $output_path = Join-Path -Path $temp_path -ChildPath $temp_foldername
- New-Item -Path $output_path -ItemType Directory | Out-Null
-
- $expand_args = @($msu, $output_path, "-F:*")
-
- try {
- &expand.exe $expand_args | Out-NUll
- } catch {
- Fail-Json $result "failed to run expand.exe $($expand_args): $($_.Exception.Message)"
- }
- if ($LASTEXITCODE -ne 0) {
- Fail-Json $result "failed to run expand.exe $($expand_args): RC = $LASTEXITCODE"
- }
-
- return $output_path
-}
-
-Function Get-HotfixMetadataFromName($name) {
- try {
- $dism_package_info = Get-WindowsPackage -Online -PackageName $name
- } catch {
- # build a basic stub for a missing result
- $dism_package_info = @{
- PackageState = "NotPresent"
- Description = ""
- PackageName = $name
- }
- }
-
- if ($dism_package_info.Description -match "(KB\d*)") {
- $hotfix_kb = $Matches[0]
- } else {
- $hotfix_kb = "UNKNOWN"
- }
-
- $metadata = @{
- name = $dism_package_info.PackageName
- state = $dism_package_info.PackageState
- kb = $hotfix_kb
- }
-
- return $metadata
-}
-
-Function Get-HotfixMetadataFromFile($extract_path) {
- # MSU contents https://support.microsoft.com/en-us/help/934307/description-of-the-windows-update-standalone-installer-in-windows
- $metadata_path = Get-ChildItem -Path $extract_path | Where-Object { $_.Extension -eq ".xml" }
- if ($null -eq $metadata_path) {
- Fail-Json $result "failed to get metadata xml inside MSU file, cannot get hotfix metadata required for this task"
- }
- [xml]$xml = Get-Content -Path $metadata_path.FullName
-
- $cab_source_filename = $xml.unattend.servicing.package.source.GetAttribute("location")
- $cab_source_filename = Split-Path -Path $cab_source_filename -Leaf
- $cab_file = Join-Path -Path $extract_path -ChildPath $cab_source_filename
-
- try {
- $dism_package_info = Get-WindowsPackage -Online -PackagePath $cab_file
- } catch {
- Fail-Json $result "failed to get DISM package metadata from path $($extract_path): $($_.Exception.Message)"
- }
- if ($dism_package_info.Applicable -eq $false) {
- Fail-Json $result "hotfix package is not applicable for this server"
- }
-
- $package_properties_path = Get-ChildItem -Path $extract_path | Where-Object { $_.Extension -eq ".txt" }
- if ($null -eq $package_properties_path) {
- $hotfix_kb = "UNKNOWN"
- } else {
- $package_ini = Get-Content -Path $package_properties_path.FullName
- $entry = $package_ini | Where-Object { $_.StartsWith("KB Article Number") }
- if ($null -eq $entry) {
- $hotfix_kb = "UNKNOWN"
- } else {
- $hotfix_kb = ($entry -split '=')[-1]
- $hotfix_kb = "KB$($hotfix_kb.Substring(1, $hotfix_kb.Length - 2))"
- }
- }
-
- $metadata = @{
- path = $cab_file
- name = $dism_package_info.PackageName
- state = $dism_package_info.PackageState
- kb = $hotfix_kb
- }
-
- return $metadata
-}
-
-Function Get-HotfixMetadataFromKB($kb) {
- # I really hate doing it this way
- $packages = Get-WindowsPackage -Online
- $identifier = $packages | Where-Object { $_.PackageName -like "*$kb*" }
-
- if ($null -eq $identifier) {
- # still haven't found the KB, need to loop through the results and check the description
- foreach ($package in $packages) {
- $raw_metadata = Get-HotfixMetadataFromName -name $package.PackageName
- if ($raw_metadata.kb -eq $kb) {
- $identifier = $raw_metadata
- break
- }
- }
-
- # if we still haven't found the package then we need to throw an error
- if ($null -eq $metadata) {
- Fail-Json $result "failed to get DISM package from KB, to continue specify hotfix_identifier instead"
- }
- } else {
- $metadata = Get-HotfixMetadataFromName -name $identifier.PackageName
- }
-
- return $metadata
-}
-
-if ($state -eq "absent") {
- # uninstall hotfix
- # this is a pretty poor way of doing this, is there a better way?
-
- if ($null -ne $hotfix_identifier) {
- $hotfix_metadata = Get-HotfixMetadataFromName -name $hotfix_identifier
- } elseif ($null -ne $hotfix_kb) {
- $hotfix_install_info = Get-Hotfix -Id $hotfix_kb -ErrorAction SilentlyContinue
- if ($null -ne $hotfix_install_info) {
- $hotfix_metadata = Get-HotfixMetadataFromKB -kb $hotfix_kb
- } else {
- $hotfix_metadata = @{state = "NotPresent"}
- }
- } else {
- Fail-Json $result "either hotfix_identifier or hotfix_kb needs to be set when state=absent"
- }
-
- # how do we want to deal with the other states?
- if ($hotfix_metadata.state -eq "UninstallPending") {
- $result.identifier = $hotfix_metadata.name
- $result.kb = $hotfix_metadata.kb
- $result.reboot_required = $true
- } elseif ($hotfix_metadata.state -eq "Installed") {
- $result.identifier = $hotfix_metadata.name
- $result.kb = $hotfix_metadata.kb
-
- if (-not $check_mode) {
- try {
- $remove_result = Remove-WindowsPackage -Online -PackageName $hotfix_metadata.name -NoRestart
- } catch {
- Fail-Json $result "failed to remove package $($hotfix_metadata.name): $($_.Exception.Message)"
- }
- $result.reboot_required = $remove_Result.RestartNeeded
- }
-
- $result.changed = $true
- }
-} else {
- if ($null -eq $source) {
- Fail-Json $result "source must be set when state=present"
- }
- if (-not (Test-Path -Path $source -PathType Leaf)) {
- Fail-Json $result "the path set for source $source does not exist or is not a file"
- }
-
- # while we do extract the file in check mode we need to do so for valid checking
- $extract_path = Extract-MSU -msu $source
- try {
- $hotfix_metadata = Get-HotfixMetadataFromFile -extract_path $extract_path
-
- # validate the hotfix matches if the hotfix id has been passed in
- if ($null -ne $hotfix_identifier) {
- if ($hotfix_metadata.name -ne $hotfix_identifier) {
- Fail-Json $result "the hotfix identifier $hotfix_identifier does not match with the source msu identifier $($hotfix_metadata.name), please omit or specify the correct identifier to continue"
- }
- }
- if ($null -ne $hotfix_kb) {
- if ($hotfix_metadata.kb -ne $hotfix_kb) {
- Fail-Json $result "the hotfix KB $hotfix_kb does not match with the source msu KB $($hotfix_metadata.kb), please omit or specify the correct KB to continue"
- }
- }
-
- $result.identifier = $hotfix_metadata.name
- $result.kb = $hotfix_metadata.kb
-
- # how do we want to deal with other states
- if ($hotfix_metadata.state -eq "InstallPending") {
- # return the reboot required flag, should we fail here instead
- $result.reboot_required = $true
- } elseif ($hotfix_metadata.state -ne "Installed") {
- if (-not $check_mode) {
- try {
- $install_result = Add-WindowsPackage -Online -PackagePath $hotfix_metadata.path -NoRestart
- } catch {
- Fail-Json $result "failed to add windows package from path $($hotfix_metadata.path): $($_.Exception.Message)"
- }
- $result.reboot_required = $install_result.RestartNeeded
- }
- $result.changed = $true
- }
- } finally {
- Remove-Item -Path $extract_path -Force -Recurse
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_hotfix.py b/lib/ansible/modules/windows/win_hotfix.py
deleted file mode 100644
index f5f3bb9c05..0000000000
--- a/lib/ansible/modules/windows/win_hotfix.py
+++ /dev/null
@@ -1,142 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub, actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_hotfix
-version_added: '2.4'
-short_description: Install and uninstalls Windows hotfixes
-description:
-- Install, uninstall a Windows hotfix.
-options:
- hotfix_identifier:
- description:
- - The name of the hotfix as shown in DISM, see examples for details.
- - This or C(hotfix_kb) MUST be set when C(state=absent).
- - If C(state=present) then the hotfix at C(source) will be validated
- against this value, if it does not match an error will occur.
- - You can get the identifier by running
- 'Get-WindowsPackage -Online -PackagePath path-to-cab-in-msu' after
- expanding the msu file.
- type: str
- hotfix_kb:
- description:
- - The name of the KB the hotfix relates to, see examples for details.
- - This or C(hotfix_identifier) MUST be set when C(state=absent).
- - If C(state=present) then the hotfix at C(source) will be validated
- against this value, if it does not match an error will occur.
- - Because DISM uses the identifier as a key and doesn't refer to a KB in
- all cases it is recommended to use C(hotfix_identifier) instead.
- type: str
- state:
- description:
- - Whether to install or uninstall the hotfix.
- - When C(present), C(source) MUST be set.
- - When C(absent), C(hotfix_identifier) or C(hotfix_kb) MUST be set.
- type: str
- default: present
- choices: [ absent, present ]
- source:
- description:
- - The path to the downloaded hotfix .msu file.
- - This MUST be set if C(state=present) and MUST be a .msu hotfix file.
- type: path
-notes:
-- This must be run on a host that has the DISM powershell module installed and
- a Powershell version >= 4.
-- This module is installed by default on Windows 8 and Server 2012 and newer.
-- You can manually install this module on Windows 7 and Server 2008 R2 by
- installing the Windows ADK
- U(https://developer.microsoft.com/en-us/windows/hardware/windows-assessment-deployment-kit),
- see examples to see how to do it with chocolatey.
-- You can download hotfixes from U(https://www.catalog.update.microsoft.com/Home.aspx).
-seealso:
-- module: win_package
-- module: win_updates
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Install Windows ADK with DISM for Server 2008 R2
- win_chocolatey:
- name: windows-adk
- version: 8.100.26866.0
- state: present
- install_args: /features OptionId.DeploymentTools
-
-- name: Install hotfix without validating the KB and Identifier
- win_hotfix:
- source: C:\temp\windows8.1-kb3172729-x64_e8003822a7ef4705cbb65623b72fd3cec73fe222.msu
- state: present
- register: hotfix_install
-
-- win_reboot:
- when: hotfix_install.reboot_required
-
-- name: Install hotfix validating KB
- win_hotfix:
- hotfix_kb: KB3172729
- source: C:\temp\windows8.1-kb3172729-x64_e8003822a7ef4705cbb65623b72fd3cec73fe222.msu
- state: present
- register: hotfix_install
-
-- win_reboot:
- when: hotfix_install.reboot_required
-
-- name: Install hotfix validating Identifier
- win_hotfix:
- hotfix_identifier: Package_for_KB3172729~31bf3856ad364e35~amd64~~6.3.1.0
- source: C:\temp\windows8.1-kb3172729-x64_e8003822a7ef4705cbb65623b72fd3cec73fe222.msu
- state: present
- register: hotfix_install
-
-- win_reboot:
- when: hotfix_install.reboot_required
-
-- name: Uninstall hotfix with Identifier
- win_hotfix:
- hotfix_identifier: Package_for_KB3172729~31bf3856ad364e35~amd64~~6.3.1.0
- state: absent
- register: hotfix_uninstall
-
-- win_reboot:
- when: hotfix_uninstall.reboot_required
-
-- name: Uninstall hotfix with KB (not recommended)
- win_hotfix:
- hotfix_kb: KB3172729
- state: absent
- register: hotfix_uninstall
-
-- win_reboot:
- when: hotfix_uninstall.reboot_required
-'''
-
-RETURN = r'''
-identifier:
- description: The DISM identifier for the hotfix.
- returned: success
- type: str
- sample: Package_for_KB3172729~31bf3856ad364e35~amd64~~6.3.1.0
-kb:
- description: The KB the hotfix relates to.
- returned: success
- type: str
- sample: KB3172729
-reboot_required:
- description: Whether a reboot is required for the install or uninstall to
- finalise.
- returned: success
- type: str
- sample: true
-'''
diff --git a/lib/ansible/modules/windows/win_http_proxy.ps1 b/lib/ansible/modules/windows/win_http_proxy.ps1
deleted file mode 100644
index 04ea473b99..0000000000
--- a/lib/ansible/modules/windows/win_http_proxy.ps1
+++ /dev/null
@@ -1,267 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.AddType
-
-$spec = @{
- options = @{
- bypass = @{ type = "list" }
- proxy = @{ type = "raw" }
- source = @{ type = "str"; choices = @("ie") }
- }
- mutually_exclusive = @(
- @("proxy", "source"),
- @("bypass", "source")
- )
- required_by = @{
- bypass = @("proxy")
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$proxy = $module.Params.proxy
-$bypass = $module.Params.bypass
-$source = $module.Params.source
-
-# Parse the raw value, it should be a Dictionary or String
-if ($proxy -is [System.Collections.IDictionary]) {
- $valid_keys = [System.Collections.Generic.List`1[String]]@("http", "https", "ftp", "socks")
- # Check to make sure we don't have any invalid keys in the dict
- $invalid_keys = [System.Collections.Generic.List`1[String]]@()
- foreach ($k in $proxy.Keys) {
- if ($k -notin $valid_keys) {
- $invalid_keys.Add($k)
- }
- }
-
- if ($invalid_keys.Count -gt 0) {
- $invalid_keys = $invalid_keys | Sort-Object # So our test assertion doesn't fail due to random ordering
- $module.FailJson("Invalid keys found in proxy: $($invalid_keys -join ', '). Valid keys are $($valid_keys -join ', ').")
- }
-
- # Build the proxy string in the form 'protocol=host;', the order of valid_keys is also important
- $proxy_list = [System.Collections.Generic.List`1[String]]@()
- foreach ($k in $valid_keys) {
- if ($proxy.ContainsKey($k)) {
- $proxy_list.Add("$k=$($proxy.$k)")
- }
- }
- $proxy = $proxy_list -join ";"
-} elseif ($null -ne $proxy) {
- $proxy = $proxy.ToString()
-}
-
-if ($bypass) {
- if ([System.String]::IsNullOrEmpty($proxy)) {
- $module.FailJson("missing parameter(s) required by ''bypass'': proxy")
- }
- $bypass = $bypass -join ';'
-}
-
-$win_http_invoke = @'
-using System;
-using System.Runtime.InteropServices;
-
-namespace Ansible.WinHttpProxy
-{
- internal class NativeHelpers
- {
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public class WINHTTP_CURRENT_USER_IE_PROXY_CONFIG : IDisposable
- {
- public bool fAutoDetect;
- public IntPtr lpszAutoConfigUrl;
- public IntPtr lpszProxy;
- public IntPtr lpszProxyBypass;
-
- public void Dispose()
- {
- if (lpszAutoConfigUrl != IntPtr.Zero)
- Marshal.FreeHGlobal(lpszAutoConfigUrl);
- if (lpszProxy != IntPtr.Zero)
- Marshal.FreeHGlobal(lpszProxy);
- if (lpszProxyBypass != IntPtr.Zero)
- Marshal.FreeHGlobal(lpszProxyBypass);
- GC.SuppressFinalize(this);
- }
- ~WINHTTP_CURRENT_USER_IE_PROXY_CONFIG() { this.Dispose(); }
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public class WINHTTP_PROXY_INFO : IDisposable
- {
- public UInt32 dwAccessType;
- public IntPtr lpszProxy;
- public IntPtr lpszProxyBypass;
-
- public void Dispose()
- {
- if (lpszProxy != IntPtr.Zero)
- Marshal.FreeHGlobal(lpszProxy);
- if (lpszProxyBypass != IntPtr.Zero)
- Marshal.FreeHGlobal(lpszProxyBypass);
- GC.SuppressFinalize(this);
- }
- ~WINHTTP_PROXY_INFO() { this.Dispose(); }
- }
- }
-
- internal class NativeMethods
- {
- [DllImport("Winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool WinHttpGetDefaultProxyConfiguration(
- [Out] NativeHelpers.WINHTTP_PROXY_INFO pProxyInfo);
-
- [DllImport("Winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool WinHttpGetIEProxyConfigForCurrentUser(
- [Out] NativeHelpers.WINHTTP_CURRENT_USER_IE_PROXY_CONFIG pProxyConfig);
-
- [DllImport("Winhttp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool WinHttpSetDefaultProxyConfiguration(
- NativeHelpers.WINHTTP_PROXY_INFO pProxyInfo);
- }
-
- public class Win32Exception : System.ComponentModel.Win32Exception
- {
- private string _msg;
-
- public Win32Exception(string message) : this(Marshal.GetLastWin32Error(), message) { }
- public Win32Exception(int errorCode, string message) : base(errorCode)
- {
- _msg = String.Format("{0} ({1}, Win32ErrorCode {2})", message, base.Message, errorCode);
- }
-
- public override string Message { get { return _msg; } }
- public static explicit operator Win32Exception(string message) { return new Win32Exception(message); }
- }
-
- public class WinINetProxy
- {
- public bool AutoDetect;
- public string AutoConfigUrl;
- public string Proxy;
- public string ProxyBypass;
- }
-
- public class WinHttpProxy
- {
- public string Proxy;
- public string ProxyBypass;
-
- public WinHttpProxy()
- {
- Refresh();
- }
-
- public void Set()
- {
- using (NativeHelpers.WINHTTP_PROXY_INFO proxyInfo = new NativeHelpers.WINHTTP_PROXY_INFO())
- {
- if (String.IsNullOrEmpty(Proxy))
- proxyInfo.dwAccessType = 1; // WINHTTP_ACCESS_TYPE_NO_PROXY
- else
- {
- proxyInfo.dwAccessType = 3; // WINHTTP_ACCESS_TYPE_NAMED_PROXY
- proxyInfo.lpszProxy = Marshal.StringToHGlobalUni(Proxy);
-
- if (!String.IsNullOrEmpty(ProxyBypass))
- proxyInfo.lpszProxyBypass = Marshal.StringToHGlobalUni(ProxyBypass);
- }
-
- if (!NativeMethods.WinHttpSetDefaultProxyConfiguration(proxyInfo))
- throw new Win32Exception("WinHttpSetDefaultProxyConfiguration() failed");
- }
- }
-
- public void Refresh()
- {
- using (NativeHelpers.WINHTTP_PROXY_INFO proxyInfo = new NativeHelpers.WINHTTP_PROXY_INFO())
- {
- if (!NativeMethods.WinHttpGetDefaultProxyConfiguration(proxyInfo))
- throw new Win32Exception("WinHttpGetDefaultProxyConfiguration() failed");
-
- Proxy = Marshal.PtrToStringUni(proxyInfo.lpszProxy);
- ProxyBypass = Marshal.PtrToStringUni(proxyInfo.lpszProxyBypass);
- }
- }
-
- public static WinINetProxy GetIEProxyConfig()
- {
- using (NativeHelpers.WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxy = new NativeHelpers.WINHTTP_CURRENT_USER_IE_PROXY_CONFIG())
- {
- if (!NativeMethods.WinHttpGetIEProxyConfigForCurrentUser(ieProxy))
- throw new Win32Exception("WinHttpGetIEProxyConfigForCurrentUser() failed");
-
- return new WinINetProxy
- {
- AutoDetect = ieProxy.fAutoDetect,
- AutoConfigUrl = Marshal.PtrToStringUni(ieProxy.lpszAutoConfigUrl),
- Proxy = Marshal.PtrToStringUni(ieProxy.lpszProxy),
- ProxyBypass = Marshal.PtrToStringUni(ieProxy.lpszProxyBypass),
- };
- }
- }
- }
-}
-'@
-Add-CSharpType -References $win_http_invoke -AnsibleModule $module
-
-$actual_proxy = New-Object -TypeName Ansible.WinHttpProxy.WinHttpProxy
-
-$module.Diff.before = @{
- proxy = $actual_proxy.Proxy
- bypass = $actual_proxy.ProxyBypass
-}
-
-if ($source -eq "ie") {
- # If source=ie we need to get the server and bypass values from the IE configuration
- $ie_proxy = [Ansible.WinHttpProxy.WinHttpProxy]::GetIEProxyConfig()
- $proxy = $ie_proxy.Proxy
- $bypass = $ie_proxy.ProxyBypass
-}
-
-$previous_proxy = $actual_proxy.Proxy
-$previous_bypass = $actual_proxy.ProxyBypass
-
-# Make sure an empty string is converted to $null for easier comparisons
-if ([String]::IsNullOrEmpty($proxy)) {
- $proxy = $null
-}
-if ([String]::IsNullOrEmpty($bypass)) {
- $bypass = $null
-}
-
-if ($previous_proxy -ne $proxy -or $previous_bypass -ne $bypass) {
- $actual_proxy.Proxy = $proxy
- $actual_proxy.ProxyBypass = $bypass
-
- if (-not $module.CheckMode) {
- $actual_proxy.Set()
-
- # Validate that the change was made correctly and revert if it wasn't. The Set() method won't fail on invalid
- # values so we need to check again to make sure all was good.
- $actual_proxy.Refresh()
- if ($actual_proxy.Proxy -ne $proxy -or $actual_proxy.ProxyBypass -ne $bypass) {
- $actual_proxy.Proxy = $previous_proxy
- $actual_proxy.ProxyBypass = $previous_bypass
- $actual_proxy.Set()
-
- $module.FailJson("Unknown error when trying to set proxy '$proxy' or bypass '$bypass'")
- }
- }
-
- $module.Result.changed = $true
-}
-
-$module.Diff.after = @{
- proxy = $proxy
- bypass = $bypass
-}
-
-$module.ExitJson()
-
diff --git a/lib/ansible/modules/windows/win_http_proxy.py b/lib/ansible/modules/windows/win_http_proxy.py
deleted file mode 100644
index d9abb858e2..0000000000
--- a/lib/ansible/modules/windows/win_http_proxy.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2019, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_http_proxy
-version_added: '2.8'
-short_description: Manages proxy settings for WinHTTP
-description:
-- Used to set, remove, or import proxy settings for Windows HTTP Services
- C(WinHTTP).
-- WinHTTP is a framework used by applications or services, typically .NET
- applications or non-interactive services, to make web requests.
-options:
- bypass:
- description:
- - A list of hosts that will bypass the set proxy when being accessed.
- - Use C(<local>) to match hostnames that are not fully qualified domain
- names. This is useful when needing to connect to intranet sites using
- just the hostname.
- - Omit, set to null or an empty string/list to remove the bypass list.
- - If this is set then I(proxy) must also be set.
- type: list
- proxy:
- description:
- - A string or dict that specifies the proxy to be set.
- - If setting a string, should be in the form C(hostname), C(hostname:port),
- or C(protocol=hostname:port).
- - If the port is undefined, the default port for the protocol in use is
- used.
- - If setting a dict, the keys should be the protocol and the values should
- be the hostname and/or port for that protocol.
- - Valid protocols are C(http), C(https), C(ftp), and C(socks).
- - Omit, set to null or an empty string to remove the proxy settings.
- source:
- description:
- - Instead of manually specifying the I(proxy) and/or I(bypass), set this to
- import the proxy from a set source like Internet Explorer.
- - Using C(ie) will import the Internet Explorer proxy settings for the
- current active network connection of the current user.
- - Only IE's proxy URL and bypass list will be imported into WinHTTP.
- - This is like running C(netsh winhttp import proxy source=ie).
- - The value is imported when the module runs and will not automatically
- be updated if the IE configuration changes in the future. The module will
- have to be run again to sync the latest changes.
- choices:
- - ie
- type: str
-notes:
-- This is not the same as the proxy settings set in Internet Explorer, also
- known as C(WinINet); use the M(win_inet_proxy) module to manage that instead.
-- These settings are set system wide and not per user, it will require
- Administrative privileges to run.
-seealso:
-- module: win_inet_proxy
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Set a proxy to use for all protocols
- win_http_proxy:
- proxy: hostname
-
-- name: Set a proxy with a specific port with a bypass list
- win_http_proxy:
- proxy: hostname:8080
- bypass:
- - server1
- - server2
- - <local>
-
-- name: Set the proxy based on the IE proxy settings
- win_http_proxy:
- source: ie
-
-- name: Set a proxy for specific protocols
- win_http_proxy:
- proxy:
- http: hostname:8080
- https: hostname:8443
-
-- name: Set a proxy for specific protocols using a string
- win_http_proxy:
- proxy: http=hostname:8080;https=hostname:8443
- bypass: server1,server2,<local>
-
-- name: Remove any proxy settings
- win_http_proxy:
- proxy: ''
- bypass: ''
-'''
-
-RETURN = r'''
-#
-'''
diff --git a/lib/ansible/modules/windows/win_iis_virtualdirectory.ps1 b/lib/ansible/modules/windows/win_iis_virtualdirectory.ps1
deleted file mode 100644
index 7d63897994..0000000000
--- a/lib/ansible/modules/windows/win_iis_virtualdirectory.ps1
+++ /dev/null
@@ -1,99 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-$params = Parse-Args $args
-$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
-$site = Get-AnsibleParam -obj $params -name "site" -type "str" -failifempty $true
-$application = Get-AnsibleParam -obj $params -name "application" -type "str"
-$physical_path = Get-AnsibleParam -obj $params -name "physical_path" -type "str"
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent","present"
-
-# Ensure WebAdministration module is loaded
-if ($null -eq (Get-Module "WebAdministration" -ErrorAction SilentlyContinue)) {
- Import-Module WebAdministration
-}
-
-# Result
-$result = @{
- directory = @{}
- changed = $false
-};
-
-# Construct path
-$directory_path = if($application) {
- "IIS:\Sites\$($site)\$($application)\$($name)"
-} else {
- "IIS:\Sites\$($site)\$($name)"
-}
-
-# Directory info
-$directory = if($application) {
- Get-WebVirtualDirectory -Site $site -Name $name -Application $application
-} else {
- Get-WebVirtualDirectory -Site $site -Name $name
-}
-
-try {
- # Add directory
- If(($state -eq 'present') -and (-not $directory)) {
- If (-not $physical_path) {
- Fail-Json -obj $result -message "missing required arguments: physical_path"
- }
- If (-not (Test-Path $physical_path)) {
- Fail-Json -obj $result -message "specified folder must already exist: physical_path"
- }
-
- $directory_parameters = @{
- Site = $site
- Name = $name
- PhysicalPath = $physical_path
- }
-
- If ($application) {
- $directory_parameters.Application = $application
- }
-
- $directory = New-WebVirtualDirectory @directory_parameters -Force
- $result.changed = $true
- }
-
- # Remove directory
- If ($state -eq 'absent' -and $directory) {
- Remove-Item $directory_path -Recurse -Force
- $result.changed = $true
- }
-
- $directory = Get-WebVirtualDirectory -Site $site -Name $name
- If($directory) {
-
- # Change Physical Path if needed
- if($physical_path) {
- If (-not (Test-Path $physical_path)) {
- Fail-Json -obj $result -message "specified folder must already exist: physical_path"
- }
-
- $vdir_folder = Get-Item $directory.PhysicalPath
- $folder = Get-Item $physical_path
- If($folder.FullName -ne $vdir_folder.FullName) {
- Set-ItemProperty $directory_path -name physicalPath -value $physical_path
- $result.changed = $true
- }
- }
- }
-} catch {
- Fail-Json $result $_.Exception.Message
-}
-
-# Result
-$directory = Get-WebVirtualDirectory -Site $site -Name $name
-$result.directory = @{
- PhysicalPath = $directory.PhysicalPath
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_iis_virtualdirectory.py b/lib/ansible/modules/windows/win_iis_virtualdirectory.py
deleted file mode 100644
index a8cc49e072..0000000000
--- a/lib/ansible/modules/windows/win_iis_virtualdirectory.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_iis_virtualdirectory
-version_added: "2.0"
-short_description: Configures a virtual directory in IIS
-description:
- - Creates, Removes and configures a virtual directory in IIS.
-options:
- name:
- description:
- - The name of the virtual directory to create or remove.
- type: str
- required: yes
- state:
- description:
- - Whether to add or remove the specified virtual directory.
- - Removing will remove the virtual directory and all under it (Recursively).
- type: str
- choices: [ absent, present ]
- default: present
- site:
- description:
- - The site name under which the virtual directory is created or exists.
- type: str
- required: yes
- application:
- description:
- - The application under which the virtual directory is created or exists.
- type: str
- physical_path:
- description:
- - The physical path to the folder in which the new virtual directory is created.
- - The specified folder must already exist.
- type: str
-seealso:
-- module: win_iis_webapplication
-- module: win_iis_webapppool
-- module: win_iis_webbinding
-- module: win_iis_website
-author:
-- Henrik Wallström (@henrikwallstrom)
-'''
-
-EXAMPLES = r'''
-- name: Create a virtual directory if it does not exist
- win_iis_virtualdirectory:
- name: somedirectory
- site: somesite
- state: present
- physical_path: C:\virtualdirectory\some
-
-- name: Remove a virtual directory if it exists
- win_iis_virtualdirectory:
- name: somedirectory
- site: somesite
- state: absent
-
-- name: Create a virtual directory on an application if it does not exist
- win_iis_virtualdirectory:
- name: somedirectory
- site: somesite
- application: someapp
- state: present
- physical_path: C:\virtualdirectory\some
-'''
diff --git a/lib/ansible/modules/windows/win_iis_webapplication.ps1 b/lib/ansible/modules/windows/win_iis_webapplication.ps1
deleted file mode 100644
index 92fdbbd9e5..0000000000
--- a/lib/ansible/modules/windows/win_iis_webapplication.ps1
+++ /dev/null
@@ -1,138 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$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
-$site = Get-AnsibleParam -obj $params -name "site" -type "str" -failifempty $true
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent","present"
-$physical_path = Get-AnsibleParam -obj $params -name "physical_path" -type "str" -aliases "path"
-$application_pool = Get-AnsibleParam -obj $params -name "application_pool" -type "str"
-$connect_as = Get-AnsibleParam -obj $params -name 'connect_as' -type 'str' -validateset 'specific_user', 'pass_through'
-$username = Get-AnsibleParam -obj $params -name "username" -type "str" -failifempty ($connect_as -eq 'specific_user')
-$password = Get-AnsibleParam -obj $params -name "password" -type "str" -failifempty ($connect_as -eq 'specific_user')
-
-$result = @{
- application_pool = $application_pool
- changed = $false
- physical_path = $physical_path
-}
-
-# Ensure WebAdministration module is loaded
-if ($null -eq (Get-Module "WebAdministration" -ErrorAction SilentlyContinue)) {
- Import-Module WebAdministration
-}
-
-# Application info
-$application = Get-WebApplication -Site $site -Name $name
-$website = Get-Website -Name $site
-
-# Set ApplicationPool to current if not specified
-if (!$application_pool) {
- $application_pool = $website.applicationPool
-}
-
-try {
- # Add application
- if (($state -eq 'present') -and (-not $application)) {
- if (-not $physical_path) {
- Fail-Json $result "missing required arguments: path"
- }
- if (-not (Test-Path -Path $physical_path)) {
- Fail-Json $result "specified folder must already exist: path"
- }
-
- $application_parameters = @{
- Name = $name
- PhysicalPath = $physical_path
- Site = $site
- }
-
- if ($application_pool) {
- $application_parameters.ApplicationPool = $application_pool
- }
-
- if (-not $check_mode) {
- $application = New-WebApplication @application_parameters -Force
- }
- $result.changed = $true
- }
-
- # Remove application
- if ($state -eq 'absent' -and $application) {
- $application = Remove-WebApplication -Site $site -Name $name -WhatIf:$check_mode
- $result.changed = $true
- }
-
- $application = Get-WebApplication -Site $site -Name $name
- if ($application) {
-
- # Change Physical Path if needed
- if ($physical_path) {
- if (-not (Test-Path -Path $physical_path)) {
- Fail-Json $result "specified folder must already exist: path"
- }
-
- $app_folder = Get-Item $application.PhysicalPath
- $folder = Get-Item $physical_path
- if ($folder.FullName -ne $app_folder.FullName) {
- Set-ItemProperty "IIS:\Sites\$($site)\$($name)" -name physicalPath -value $physical_path -WhatIf:$check_mode
- $result.changed = $true
- }
- }
-
- # Change Application Pool if needed
- if ($application_pool) {
- if ($application_pool -ne $application.applicationPool) {
- Set-ItemProperty "IIS:\Sites\$($site)\$($name)" -name applicationPool -value $application_pool -WhatIf:$check_mode
- $result.changed = $true
- }
- }
-
- # Change username and password if needed
- $app_user = Get-ItemProperty -Path "IIS:\Sites\$($site)\$($name)" -Name 'userName'
- $app_pass = Get-ItemProperty -Path "IIS:\Sites\$($site)\$($name)" -Name 'password'
- if ($connect_as -eq 'pass_through') {
- if ($app_user -ne '') {
- Clear-ItemProperty -Path "IIS:\Sites\$($site)\$($name)" -Name 'userName' -WhatIf:$check_mode
- $result.changed = $true
- }
- if ($app_pass -ne '') {
- Clear-ItemProperty -Path "IIS:\Sites\$($site)\$($name)" -Name 'password' -WhatIf:$check_mode
- $result.changed = $true
- }
- } elseif ($connect_as -eq 'specific_user') {
- if ($app_user -ne $username) {
- Set-ItemProperty -Path "IIS:\Sites\$($site)\$($name)" -Name 'userName' -Value $username -WhatIf:$check_mode
- $result.changed = $true
- }
- if ($app_pass -ne $password) {
- Set-ItemProperty -Path "IIS:\Sites\$($site)\$($name)" -Name 'password' -Value $password -WhatIf:$check_mode
- $result.changed = $true
- }
- }
- }
-} catch {
- Fail-Json $result $_.Exception.Message
-}
-
-# When in check-mode or on removal, this may fail
-$application = Get-WebApplication -Site $site -Name $name
-if ($application) {
- $app_user = Get-ItemProperty -Path "IIS:\Sites\$($site)\$($name)" -Name 'userName'
- if ($app_user -eq '') {
- $result.connect_as = 'pass_through'
- } else {
- $result.connect_as = 'specific_user'
- }
-
- $result.physical_path = $application.PhysicalPath
- $result.application_pool = $application.ApplicationPool
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_iis_webapplication.py b/lib/ansible/modules/windows/win_iis_webapplication.py
deleted file mode 100644
index 2fad6a4807..0000000000
--- a/lib/ansible/modules/windows/win_iis_webapplication.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_iis_webapplication
-version_added: "2.0"
-short_description: Configures IIS web applications
-description:
-- Creates, removes, and configures IIS web applications.
-options:
- name:
- description:
- - Name of the web application.
- type: str
- required: yes
- site:
- description:
- - Name of the site on which the application is created.
- type: str
- required: yes
- state:
- description:
- - State of the web application.
- type: str
- choices: [ absent, present ]
- default: present
- physical_path:
- description:
- - The physical path on the remote host to use for the new application.
- - The specified folder must already exist.
- type: str
- application_pool:
- description:
- - The application pool in which the new site executes.
- - If not specified, the application pool of the current website will be used.
- type: str
- connect_as:
- description:
- - The type of authentication to use for this application. Either C(pass_through) or C(specific_user)
- - If C(pass_through), IIS will use the identity of the user or application pool identity to access the file system or network.
- - If C(specific_user), IIS will use the credentials provided in I(username) and I(password) to access the file system or network.
- type: str
- choices: [pass_through, specific_user]
- version_added: '2.10'
- username:
- description:
- - Specifies the user name of an account that can access configuration files and content for this application.
- - Required when I(connect_as) is set to C(specific_user).
- type: str
- version_added: '2.10'
- password:
- description:
- - The password associated with I(username).
- - Required when I(connect_as) is set to C(specific_user).
- type: str
- version_added: '2.10'
-seealso:
-- module: win_iis_virtualdirectory
-- module: win_iis_webapppool
-- module: win_iis_webbinding
-- module: win_iis_website
-author:
-- Henrik Wallström (@henrikwallstrom)
-'''
-
-EXAMPLES = r'''
-- name: Add ACME webapplication on IIS.
- win_iis_webapplication:
- name: api
- site: acme
- state: present
- physical_path: C:\apps\acme\api
-'''
-
-RETURN = r'''
-application_pool:
- description: The used/implemented application_pool value.
- returned: success
- type: str
- sample: DefaultAppPool
-physical_path:
- description: The used/implemented physical_path value.
- returned: success
- type: str
- sample: C:\apps\acme\api
-connect_as:
- description: How IIS will try to authenticate to the physical_path.
- returned: when the application exists
- type: str
- sample: specific_user
-'''
diff --git a/lib/ansible/modules/windows/win_iis_webapppool.ps1 b/lib/ansible/modules/windows/win_iis_webapppool.ps1
deleted file mode 100644
index 79167ba02e..0000000000
--- a/lib/ansible/modules/windows/win_iis_webapppool.ps1
+++ /dev/null
@@ -1,307 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = 'Stop'
-
-$params = Parse-Args -arguments $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 "started","restarted","stopped","absent","present"
-$result = @{
- changed = $false
- attributes = @{}
- info = @{
- name = $name
- state = $state
- attributes = @{}
- cpu = @{}
- failure = @{}
- processModel = @{}
- recycling = @{
- periodicRestart = @{}
- }
- }
-}
-
-# Stores the free form attributes for the module
-$attributes = @{}
-$input_attributes = Get-AnsibleParam -obj $params -name "attributes"
-if ($input_attributes) {
- if ($input_attributes -is [System.Collections.Hashtable]) {
- # Uses dict style parameters, newer and recommended style
- $attributes = $input_attributes
- } else {
- Fail-Json -obj $result -message "Using a string for the attributes parameter is not longer supported, please use a dict instead"
- }
-}
-$result.attributes = $attributes
-
-Function Get-DotNetClassForAttribute($attribute_parent) {
- switch ($attribute_parent) {
- "attributes" { [Microsoft.Web.Administration.ApplicationPool] }
- "cpu" { [Microsoft.Web.Administration.ApplicationPoolCpu] }
- "failure" { [Microsoft.Web.Administration.ApplicationPoolFailure] }
- "processModel" { [Microsoft.Web.Administration.ApplicationPoolProcessModel] }
- "recycling" { [Microsoft.Web.Administration.ApplicationPoolRecycling] }
- default { [Microsoft.Web.Administration.ApplicationPool] }
- }
-}
-
-Function Convert-CollectionToList($collection) {
- $list = @()
-
- if ($collection -is [String]) {
- $raw_list = $collection -split ","
- foreach ($entry in $raw_list) {
- $list += $entry.Trim()
- }
- } elseif ($collection -is [Microsoft.IIs.PowerShell.Framework.ConfigurationElement]) {
- # the collection is the value from IIS itself, we need to conver accordingly
- foreach ($entry in $collection.Collection) {
- $list += $entry.Value.ToString()
- }
- } elseif ($collection -isnot [Array]) {
- $list += $collection
- } else {
- $list = $collection
- }
-
- return ,$list
-}
-
-Function Compare-Values($current, $new) {
- if ($null -eq $current) {
- return $true
- }
-
- if ($current -is [Array]) {
- if ($new -isnot [Array]) {
- return $true
- }
-
- if ($current.Count -ne $new.Count) {
- return $true
- }
- for ($i = 0; $i -lt $current.Count; $i++) {
- if ($current[$i] -ne $new[$i]) {
- return $true
- }
- }
- } else {
- if ($current -ne $new) {
- return $true
- }
- }
- return $false
-}
-
-Function Convert-ToPropertyValue($pool, $attribute_key, $attribute_value) {
- # Will convert the new value to the enum value expected and cast accordingly to the type
- if ([bool]($attribute_value.PSobject.Properties -match "Value")) {
- $attribute_value = $attribute_value.Value
- }
- $attribute_key_split = $attribute_key -split "\."
- if ($attribute_key_split.Length -eq 1) {
- $attribute_parent = "attributes"
- $attribute_child = $attribute_key
- $attribute_meta = $pool.Attributes | Where-Object { $_.Name -eq $attribute_child }
- } elseif ($attribute_key_split.Length -gt 1) {
- $attribute_parent = $attribute_key_split[0]
- $attribute_key_split = $attribute_key_split[1..$($attribute_key_split.Length - 1)]
- $parent = $pool.$attribute_parent
-
- foreach ($key in $attribute_key_split) {
- $attribute_meta = $parent.Attributes | Where-Object { $_.Name -eq $key }
- $parent = $parent.$key
- if ($null -eq $attribute_meta) {
- $attribute_meta = $parent
- }
- }
- $attribute_child = $attribute_key_split[-1]
- }
-
- if ($attribute_meta) {
- if (($attribute_meta.PSObject.Properties.Name -eq "Collection").Count -gt 0) {
- return ,(Convert-CollectionToList -collection $attribute_value)
- }
- $type = $attribute_meta.Schema.Type
- $value = $attribute_value
- if ($type -eq "enum") {
- # Attempt to convert the value from human friendly to enum value - use existing value if we fail
- $dot_net_class = Get-DotNetClassForAttribute -attribute_parent $attribute_parent
- $enum_attribute_name = $attribute_child.Substring(0,1).ToUpper() + $attribute_child.Substring(1)
- $enum = $dot_net_class.GetProperty($enum_attribute_name).PropertyType.FullName
- if ($enum) {
- $enum_values = [Enum]::GetValues($enum)
- foreach ($enum_value in $enum_values) {
- if ($attribute_value.GetType() -is $enum_value.GetType()) {
- if ($enum_value -eq $attribute_value) {
- $value = $enum_value
- break
- }
- } else {
- if ([System.String]$enum_value -eq [System.String]$attribute_value) {
- $value = $enum_value
- break
- }
- }
- }
- }
- }
- # Try and cast the variable using the chosen type, revert to the default if it fails
- Set-Variable -Name casted_value -Value ($value -as ([type] $attribute_meta.TypeName))
- if ($null -eq $casted_value) {
- $value
- } else {
- $casted_value
- }
- } else {
- $attribute_value
- }
-}
-
-# Ensure WebAdministration module is loaded
-if ($null -eq (Get-Module -Name "WebAdministration" -ErrorAction SilentlyContinue)) {
- Import-Module WebAdministration
- $web_admin_dll_path = Join-Path $env:SystemRoot system32\inetsrv\Microsoft.Web.Administration.dll
- Add-Type -Path $web_admin_dll_path
-}
-
-$pool = Get-Item -Path IIS:\AppPools\$name -ErrorAction SilentlyContinue
-if ($state -eq "absent") {
- # Remove pool if present
- if ($pool) {
- try {
- Remove-WebAppPool -Name $name -WhatIf:$check_mode
- } catch {
- Fail-Json $result "Failed to remove Web App pool $($name): $($_.Exception.Message)"
- }
- $result.changed = $true
- }
-} else {
- # Add pool if absent
- if (-not $pool) {
- if (-not $check_mode) {
- try {
- New-WebAppPool -Name $name > $null
- } catch {
- Fail-Json $result "Failed to create new Web App Pool $($name): $($_.Exception.Message)"
- }
- }
- $result.changed = $true
- # If in check mode this pool won't actually exists so skip it
- if (-not $check_mode) {
- $pool = Get-Item -Path IIS:\AppPools\$name
- }
- }
-
- # Cannot run the below in check mode if the pool did not always exist
- if ($pool) {
- # Modify pool based on parameters
- foreach ($attribute in $attributes.GetEnumerator()) {
- $attribute_key = $attribute.Name
- $new_raw_value = $attribute.Value
- $new_value = Convert-ToPropertyValue -pool $pool -attribute_key $attribute_key -attribute_value $new_raw_value
-
- $current_raw_value = Get-ItemProperty -Path IIS:\AppPools\$name -Name $attribute_key -ErrorAction SilentlyContinue
- $current_value = Convert-ToPropertyValue -pool $pool -attribute_key $attribute_key -attribute_value $current_raw_value
-
- $changed = Compare-Values -current $current_value -new $new_value
- if ($changed -eq $true) {
- if ($new_value -is [Array]) {
- try {
- Clear-ItemProperty -Path IIS:\AppPools\$name -Name $attribute_key -WhatIf:$check_mode
- } catch {
- Fail-Json -obj $result -message "Failed to clear attribute to Web App Pool $name. Attribute: $attribute_key, Exception: $($_.Exception.Message)"
- }
- foreach ($value in $new_value) {
- try {
- New-ItemProperty -Path IIS:\AppPools\$name -Name $attribute_key -Value @{value=$value} -WhatIf:$check_mode > $null
- } catch {
- Fail-Json -obj $result -message "Failed to add new attribute to Web App Pool $name. Attribute: $attribute_key, Value: $value, Exception: $($_.Exception.Message)"
- }
- }
- } else {
- try {
- Set-ItemProperty -Path IIS:\AppPools\$name -Name $attribute_key -Value $new_value -WhatIf:$check_mode
- } catch {
- Fail-Json $result "Failed to set attribute to Web App Pool $name. Attribute: $attribute_key, Value: $new_value, Exception: $($_.Exception.Message)"
- }
- }
- $result.changed = $true
- }
- }
-
- # Set the state of the pool
- if ($pool.State -eq "Stopped") {
- if ($state -eq "started" -or $state -eq "restarted") {
- if (-not $check_mode) {
- try {
- Start-WebAppPool -Name $name > $null
- } catch {
- Fail-Json $result "Failed to start Web App Pool $($name): $($_.Exception.Message)"
- }
- }
- $result.changed = $true
- }
- } else {
- if ($state -eq "stopped") {
- if (-not $check_mode) {
- try {
- Stop-WebAppPool -Name $name > $null
- } catch {
- Fail-Json $result "Failed to stop Web App Pool $($name): $($_.Exception.Message)"
- }
- }
- $result.changed = $true
- } elseif ($state -eq "restarted") {
- if (-not $check_mode) {
- try {
- Restart-WebAppPool -Name $name > $null
- } catch {
- Fail-Json $result "Failed to restart Web App Pool $($name): $($_.Exception.Message)"
- }
- }
- $result.changed = $true
- }
- }
- }
-}
-
-# Get all the current attributes for the pool
-$pool = Get-Item -Path IIS:\AppPools\$name -ErrorAction SilentlyContinue
-$elements = @("attributes", "cpu", "failure", "processModel", "recycling")
-
-foreach ($element in $elements) {
- if ($element -eq "attributes") {
- $attribute_collection = $pool.Attributes
- $attribute_parent = $pool
- } else {
- $attribute_collection = $pool.$element.Attributes
- $attribute_parent = $pool.$element
- }
-
- foreach ($attribute in $attribute_collection) {
- $attribute_name = $attribute.Name
- if ($attribute_name -notlike "*password*") {
- $attribute_value = $attribute_parent.$attribute_name
-
- $result.info.$element.Add($attribute_name, $attribute_value)
- }
- }
-}
-
-# Manually get the periodicRestart attributes in recycling
-foreach ($attribute in $pool.recycling.periodicRestart.Attributes) {
- $attribute_name = $attribute.Name
- $attribute_value = $pool.recycling.periodicRestart.$attribute_name
- $result.info.recycling.periodicRestart.Add($attribute_name, $attribute_value)
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_iis_webapppool.py b/lib/ansible/modules/windows/win_iis_webapppool.py
deleted file mode 100644
index d5a79c7328..0000000000
--- a/lib/ansible/modules/windows/win_iis_webapppool.py
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_iis_webapppool
-version_added: "2.0"
-short_description: Configure IIS Web Application Pools
-description:
- - Creates, removes and configures an IIS Web Application Pool.
-options:
- attributes:
- description:
- - This field is a free form dictionary value for the application pool
- attributes.
- - These attributes are based on the naming standard at
- U(https://www.iis.net/configreference/system.applicationhost/applicationpools/add#005),
- see the examples section for more details on how to set this.
- - You can also set the attributes of child elements like cpu and
- processModel, see the examples to see how it is done.
- - While you can use the numeric values for enums it is recommended to use
- the enum name itself, e.g. use SpecificUser instead of 3 for
- processModel.identityType.
- - managedPipelineMode may be either "Integrated" or "Classic".
- - startMode may be either "OnDemand" or "AlwaysRunning".
- - Use C(state) module parameter to modify the state of the app pool.
- - When trying to set 'processModel.password' and you receive a 'Value
- does fall within the expected range' error, you have a corrupted
- keystore. Please follow
- U(http://structuredsight.com/2014/10/26/im-out-of-range-youre-out-of-range/)
- to help fix your host.
- name:
- description:
- - Name of the application pool.
- type: str
- required: yes
- state:
- description:
- - The state of the application pool.
- - If C(absent) will ensure the app pool is removed.
- - If C(present) will ensure the app pool is configured and exists.
- - If C(restarted) will ensure the app pool exists and will restart, this
- is never idempotent.
- - If C(started) will ensure the app pool exists and is started.
- - If C(stopped) will ensure the app pool exists and is stopped.
- type: str
- choices: [ absent, present, restarted, started, stopped ]
- default: present
-seealso:
-- module: win_iis_virtualdirectory
-- module: win_iis_webapplication
-- module: win_iis_webbinding
-- module: win_iis_website
-author:
-- Henrik Wallström (@henrikwallstrom)
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Return information about an existing application pool
- win_iis_webapppool:
- name: DefaultAppPool
- state: present
-
-- name: Create a new application pool in 'Started' state
- win_iis_webapppool:
- name: AppPool
- state: started
-
-- name: Stop an application pool
- win_iis_webapppool:
- name: AppPool
- state: stopped
-
-- name: Restart an application pool (non-idempotent)
- win_iis_webapppool:
- name: AppPool
- state: restarted
-
-- name: Change application pool attributes using new dict style
- win_iis_webapppool:
- name: AppPool
- attributes:
- managedRuntimeVersion: v4.0
- autoStart: no
-
-- name: Creates an application pool, sets attributes and starts it
- win_iis_webapppool:
- name: AnotherAppPool
- state: started
- attributes:
- managedRuntimeVersion: v4.0
- autoStart: no
-
-# In the below example we are setting attributes in child element processModel
-# https://www.iis.net/configreference/system.applicationhost/applicationpools/add/processmodel
-- name: Manage child element and set identity of application pool
- win_iis_webapppool:
- name: IdentitiyAppPool
- state: started
- attributes:
- managedPipelineMode: Classic
- processModel.identityType: SpecificUser
- processModel.userName: '{{ansible_user}}'
- processModel.password: '{{ansible_password}}'
- processModel.loadUserProfile: true
-
-- name: Manage a timespan attribute
- win_iis_webapppool:
- name: TimespanAppPool
- state: started
- attributes:
- # Timespan with full string "day:hour:minute:second.millisecond"
- recycling.periodicRestart.time: "00:00:05:00.000000"
- recycling.periodicRestart.schedule: ["00:10:00", "05:30:00"]
- # Shortened timespan "hour:minute:second"
- processModel.pingResponseTime: "00:03:00"
-'''
-
-RETURN = r'''
-attributes:
- description: Application Pool attributes that were set and processed by this
- module invocation.
- returned: success
- type: dict
- sample:
- enable32BitAppOnWin64: "true"
- managedRuntimeVersion: "v4.0"
- managedPipelineMode: "Classic"
-info:
- description: Information on current state of the Application Pool. See
- https://www.iis.net/configreference/system.applicationhost/applicationpools/add#005
- for the full list of return attributes based on your IIS version.
- returned: success
- type: complex
- sample:
- contains:
- attributes:
- description: Key value pairs showing the current Application Pool attributes.
- returned: success
- type: dict
- sample:
- autoStart: true
- managedRuntimeLoader: "webengine4.dll"
- managedPipelineMode: "Classic"
- name: "DefaultAppPool"
- CLRConfigFile: ""
- passAnonymousToken: true
- applicationPoolSid: "S-1-5-82-1352790163-598702362-1775843902-1923651883-1762956711"
- queueLength: 1000
- managedRuntimeVersion: "v4.0"
- state: "Started"
- enableConfigurationOverride: true
- startMode: "OnDemand"
- enable32BitAppOnWin64: true
- cpu:
- description: Key value pairs showing the current Application Pool cpu attributes.
- returned: success
- type: dict
- sample:
- action: "NoAction"
- limit: 0
- resetInterval:
- Days: 0
- Hours: 0
- failure:
- description: Key value pairs showing the current Application Pool failure attributes.
- returned: success
- type: dict
- sample:
- autoShutdownExe: ""
- orphanActionExe: ""
- rapidFailProtextionInterval:
- Days: 0
- Hours: 0
- name:
- description: Name of Application Pool that was processed by this module invocation.
- returned: success
- type: str
- sample: "DefaultAppPool"
- processModel:
- description: Key value pairs showing the current Application Pool processModel attributes.
- returned: success
- type: dict
- sample:
- identityType: "ApplicationPoolIdentity"
- logonType: "LogonBatch"
- pingInterval:
- Days: 0
- Hours: 0
- recycling:
- description: Key value pairs showing the current Application Pool recycling attributes.
- returned: success
- type: dict
- sample:
- disallowOverlappingRotation: false
- disallowRotationOnConfigChange: false
- logEventOnRecycle: "Time,Requests,Schedule,Memory,IsapiUnhealthy,OnDemand,ConfigChange,PrivateMemory"
- state:
- description: Current runtime state of the pool as the module completed.
- returned: success
- type: str
- sample: "Started"
-'''
diff --git a/lib/ansible/modules/windows/win_iis_webbinding.ps1 b/lib/ansible/modules/windows/win_iis_webbinding.ps1
deleted file mode 100644
index ffbd1866ae..0000000000
--- a/lib/ansible/modules/windows/win_iis_webbinding.ps1
+++ /dev/null
@@ -1,377 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
-# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$name = Get-AnsibleParam $params -name "name" -type str -failifempty $true -aliases 'website'
-$state = Get-AnsibleParam $params "state" -default "present" -validateSet "present","absent"
-$host_header = Get-AnsibleParam $params -name "host_header" -type str
-$protocol = Get-AnsibleParam $params -name "protocol" -type str -default 'http'
-$port = Get-AnsibleParam $params -name "port" -default '80'
-$ip = Get-AnsibleParam $params -name "ip" -default '*'
-$certificateHash = Get-AnsibleParam $params -name "certificate_hash" -type str -default ([string]::Empty)
-$certificateStoreName = Get-AnsibleParam $params -name "certificate_store_name" -type str -default ([string]::Empty)
-$sslFlags = Get-AnsibleParam $params -name "ssl_flags" -default '0' -ValidateSet '0','1','2','3'
-
-$result = @{
- changed = $false
-}
-
-#################
-### Functions ###
-#################
-function Create-BindingInfo {
- $ht = @{
- 'bindingInformation' = $args[0].bindingInformation
- 'ip' = $args[0].bindingInformation.split(':')[0]
- 'port' = [int]$args[0].bindingInformation.split(':')[1]
- 'hostheader' = $args[0].bindingInformation.split(':')[2]
- #'isDsMapperEnabled' = $args[0].isDsMapperEnabled
- 'protocol' = $args[0].protocol
- 'certificateStoreName' = $args[0].certificateStoreName
- 'certificateHash' = $args[0].certificateHash
- }
-
- #handle sslflag support
- If ([version][System.Environment]::OSVersion.Version -lt [version]'6.2')
- {
- $ht.sslFlags = 'not supported'
- }
- Else
- {
- $ht.sslFlags = [int]$args[0].sslFlags
- }
-
- Return $ht
-}
-
-# Used instead of get-webbinding to ensure we always return a single binding
-# We can't filter properly with get-webbinding...ex get-webbinding ip * returns all bindings
-# pass it $binding_parameters hashtable
-function Get-SingleWebBinding {
-
- Try {
- $site_bindings = get-webbinding -name $args[0].name
- }
- Catch {
- # 2k8r2 throws this error when you run get-webbinding with no bindings in iis
- If (-not $_.Exception.Message.CompareTo('Cannot process argument because the value of argument "obj" is null. Change the value of argument "obj" to a non-null value'))
- {
- Throw $_.Exception.Message
- }
- Else { return }
- }
-
- Foreach ($binding in $site_bindings)
- {
- $splits = $binding.bindingInformation -split ':'
-
- if (
- $args[0].protocol -eq $binding.protocol -and
- $args[0].ipaddress -eq $splits[0] -and
- $args[0].port -eq $splits[1] -and
- $args[0].hostheader -eq $splits[2]
- )
- {
- Return $binding
- }
- }
-}
-
-
-#############################
-### Pre-Action Validation ###
-#############################
-$os_version = [version][System.Environment]::OSVersion.Version
-
-# Ensure WebAdministration module is loaded
-If ($os_version -lt [version]'6.1')
-{
- Try {
- Add-PSSnapin WebAdministration
- }
- Catch {
- Fail-Json -obj $result -message "The WebAdministration snap-in is not present. Please make sure it is installed."
- }
-}
-Else
-{
- Try {
- Import-Module WebAdministration
- }
- Catch {
- Fail-Json -obj $result -message "Failed to load WebAdministration module. Is IIS installed? $($_.Exception.Message)"
- }
-}
-
-# ensure website targetted exists. -Name filter doesn't work on 2k8r2 so do where-object instead
-$website_check = get-website | Where-Object {$_.name -eq $name}
-If (-not $website_check)
-{
- Fail-Json -obj $result -message "Unable to retrieve website with name $Name. Make sure the website name is valid and exists."
-}
-
-# if OS older than 2012 (6.2) and ssl flags are set, fail. Otherwise toggle sni_support
-If ($os_version -lt [version]'6.2')
-{
- If ($sslFlags -ne 0)
- {
- Fail-Json -obj $result -message "SNI and Certificate Store support is not available for systems older than 2012 (6.2)"
- }
- $sni_support = $false #will cause the sslflags check later to skip
-}
-Else
-{
- $sni_support = $true
-}
-
-# make sure ssl flags only specified with https protocol
-If ($protocol -ne 'https' -and $sslFlags -gt 0)
-{
- Fail-Json -obj $result -message "SSLFlags can only be set for HTTPS protocol"
-}
-
-# validate certificate details if provided
-# we don't do anything with cert on state: absent, so only validate present
-If ($certificateHash -and $state -eq 'present')
-{
- If ($protocol -ne 'https')
- {
- Fail-Json -obj $result -message "You can only provide a certificate thumbprint when protocol is set to https"
- }
-
- #apply default for cert store name
- If (-Not $certificateStoreName)
- {
- $certificateStoreName = 'my'
- }
-
- #validate cert path
- $cert_path = "cert:\LocalMachine\$certificateStoreName\$certificateHash"
- If (-Not (Test-Path $cert_path) )
- {
- Fail-Json -obj $result -message "Unable to locate certificate at $cert_path"
- }
-}
-
-# make sure binding info is valid for central cert store if sslflags -gt 1
-If ($sslFlags -gt 1 -and ($certificateHash -ne [string]::Empty -or $certificateStoreName -ne [string]::Empty))
-{
- Fail-Json -obj $result -message "You set sslFlags to $sslFlags. This indicates you wish to use the Central Certificate Store feature.
- This cannot be used in combination with certficiate_hash and certificate_store_name. When using the Central Certificate Store feature,
- the certificate is automatically retrieved from the store rather than manually assigned to the binding."
-}
-
-# disallow host_header: '*'
-If ($host_header -eq '*')
-{
- Fail-Json -obj $result -message "To make or remove a catch-all binding, please omit the host_header parameter entirely rather than specify host_header *"
-}
-
-##########################
-### start action items ###
-##########################
-
-# create binding search splat
-$binding_parameters = @{
- Name = $name
- Protocol = $protocol
- Port = $port
- IPAddress = $ip
-}
-
-# insert host header to search if specified, otherwise it will return * (all bindings matching protocol/ip)
-If ($host_header)
-{
- $binding_parameters.HostHeader = $host_header
-}
-Else
-{
- $binding_parameters.HostHeader = [string]::Empty
-}
-
-# Get bindings matching parameters
-Try {
- $current_bindings = Get-SingleWebBinding $binding_parameters
-}
-Catch {
- Fail-Json -obj $result -message "Failed to retrieve bindings with Get-SingleWebBinding - $($_.Exception.Message)"
-}
-
-################################################
-### Remove binding or exit if already absent ###
-################################################
-If ($current_bindings -and $state -eq 'absent')
-{
- Try {
- #there is a bug in this method that will result in all bindings being removed if the IP in $current_bindings is a *
- #$current_bindings | Remove-WebBinding -verbose -WhatIf:$check_mode
-
- #another method that did not work. It kept failing to match on element and removed everything.
- #$element = @{protocol="$protocol";bindingInformation="$ip`:$port`:$host_header"}
- #Remove-WebconfigurationProperty -filter $current_bindings.ItemXPath -Name Bindings.collection -AtElement $element -WhatIf #:$check_mode
-
- #this method works
- [array]$bindings = Get-WebconfigurationProperty -filter $current_bindings.ItemXPath -Name Bindings.collection
-
- $index = Foreach ($item in $bindings) {
- If ( $protocol -eq $item.protocol -and $current_bindings.bindingInformation -eq $item.bindingInformation ) {
- $bindings.indexof($item)
- break
- }
- }
-
- Remove-WebconfigurationProperty -filter $current_bindings.ItemXPath -Name Bindings.collection -AtIndex $index -WhatIf:$check_mode
- $result.changed = $true
- }
-
- Catch {
- Fail-Json -obj $result -message "Failed to remove the binding from IIS - $($_.Exception.Message)"
- }
-
- # removing bindings from iis may not also remove them from iis:\sslbindings
-
- $result.operation_type = 'removed'
- $result.binding_info = $current_bindings | ForEach-Object {Create-BindingInfo $_}
- Exit-Json -obj $result
-}
-ElseIf (-Not $current_bindings -and $state -eq 'absent')
-{
- # exit changed: false since it's already gone
- Exit-Json -obj $result
-}
-
-
-################################
-### Modify existing bindings ###
-################################
-<#
-since we have already have the parameters available to get-webbinding,
-we just need to check here for the ones that are not available which are the
-ssl settings (hash, store, sslflags). If they aren't set we update here, or
-exit with changed: false
-#>
-ElseIf ($current_bindings)
-{
- #ran into a strange edge case in testing where I was able to retrieve bindings but not expand all the properties
- #when adding a self-signed wildcard cert to a binding. it seemed to permanently break the binding. only removing it
- #would cause the error to stop.
- Try {
- $null = $current_bindings | Select-Object *
- }
- Catch {
- Fail-Json -obj $result -message "Found a matching binding, but failed to expand it's properties (get-binding | FL *). In testing, this was caused by using a self-signed wildcard certificate. $($_.Exception.Message)"
- }
-
- # check if there is a match on the ssl parameters
- If ( ($current_bindings.sslFlags -ne $sslFlags -and $sni_support) -or
- $current_bindings.certificateHash -ne $certificateHash -or
- $current_bindings.certificateStoreName -ne $certificateStoreName)
- {
- # match/update SNI
- If ($current_bindings.sslFlags -ne $sslFlags -and $sni_support)
- {
- Try {
- Set-WebBinding -Name $name -IPAddress $ip -Port $port -HostHeader $host_header -PropertyName sslFlags -value $sslFlags -whatif:$check_mode
- $result.changed = $true
- }
- Catch {
- Fail-Json -obj $result -message "Failed to update sslFlags on binding - $($_.Exception.Message)"
- }
-
- # Refresh the binding object since it has been changed
- Try {
- $current_bindings = Get-SingleWebBinding $binding_parameters
- }
- Catch {
- Fail-Json -obj $result -message "Failed to refresh bindings after setting sslFlags - $($_.Exception.Message)"
- }
- }
- # match/update certificate
- If ($current_bindings.certificateHash -ne $certificateHash -or $current_bindings.certificateStoreName -ne $certificateStoreName)
- {
- If (-Not $check_mode)
- {
- Try {
- $current_bindings.AddSslCertificate($certificateHash,$certificateStoreName)
- }
- Catch {
- Fail-Json -obj $result -message "Failed to set new SSL certificate - $($_.Exception.Message)"
- }
- }
- }
- $result.changed = $true
- $result.operation_type = 'updated'
- $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
- $result.binding_info = Create-BindingInfo (Get-SingleWebBinding $binding_parameters)
- Exit-Json -obj $result #exit changed true
- }
- Else
- {
- $result.operation_type = 'matched'
- $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
- $result.binding_info = Create-BindingInfo (Get-SingleWebBinding $binding_parameters)
- Exit-Json -obj $result #exit changed false
- }
-}
-
-########################
-### Add new bindings ###
-########################
-ElseIf (-not $current_bindings -and $state -eq 'present')
-{
- # add binding. this creates the binding, but does not apply a certificate to it.
- Try
- {
- If (-not $check_mode)
- {
- If ($sni_support)
- {
- New-WebBinding @binding_parameters -SslFlags $sslFlags -Force
- }
- Else
- {
- New-WebBinding @binding_parameters -Force
- }
- }
- $result.changed = $true
- }
- Catch
- {
- $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
- Fail-Json -obj $result -message "Failed at creating new binding (note: creating binding and adding ssl are separate steps) - $($_.Exception.Message)"
- }
-
- # add certificate to binding
- If ($certificateHash -and -not $check_mode)
- {
- Try {
- #$new_binding = get-webbinding -Name $name -IPAddress $ip -port $port -Protocol $protocol -hostheader $host_header
- $new_binding = Get-SingleWebBinding $binding_parameters
- $new_binding.addsslcertificate($certificateHash,$certificateStoreName)
- }
- Catch {
- $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
- Fail-Json -obj $result -message "Failed to set new SSL certificate - $($_.Exception.Message)"
- }
- }
-
- $result.changed = $true
- $result.operation_type = 'added'
- $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
-
- # incase there are no bindings we do a check before calling Create-BindingInfo
- $web_binding = Get-SingleWebBinding $binding_parameters
- if ($web_binding) {
- $result.binding_info = Create-BindingInfo $web_binding
- } else {
- $result.binding_info = $null
- }
- Exit-Json $result
-}
diff --git a/lib/ansible/modules/windows/win_iis_webbinding.py b/lib/ansible/modules/windows/win_iis_webbinding.py
deleted file mode 100644
index 27fdd28f5c..0000000000
--- a/lib/ansible/modules/windows/win_iis_webbinding.py
+++ /dev/null
@@ -1,154 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
-# Copyright: (c) 2017, Henrik Wallström <henrik@wallstroms.nu>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_iis_webbinding
-version_added: "2.0"
-short_description: Configures a IIS Web site binding
-description:
- - Creates, removes and configures a binding to an existing IIS Web site.
-options:
- name:
- description:
- - Names of web site.
- type: str
- required: yes
- aliases: [ website ]
- state:
- description:
- - State of the binding.
- type: str
- choices: [ absent, present ]
- default: present
- port:
- description:
- - The port to bind to / use for the new site.
- type: str
- default: 80
- ip:
- description:
- - The IP address to bind to / use for the new site.
- type: str
- default: '*'
- host_header:
- description:
- - The host header to bind to / use for the new site.
- - If you are creating/removing a catch-all binding, omit this parameter rather than defining it as '*'.
- type: str
- protocol:
- description:
- - The protocol to be used for the Web binding (usually HTTP, HTTPS, or FTP).
- type: str
- default: http
- certificate_hash:
- description:
- - Certificate hash (thumbprint) for the SSL binding. The certificate hash is the unique identifier for the certificate.
- type: str
- certificate_store_name:
- description:
- - Name of the certificate store where the certificate for the binding is located.
- type: str
- default: my
- ssl_flags:
- description:
- - This parameter is only valid on Server 2012 and newer.
- - Primarily used for enabling and disabling server name indication (SNI).
- - Set to C(0) to disable SNI.
- - Set to C(1) to enable SNI.
- type: str
- version_added: "2.5"
-seealso:
-- module: win_iis_virtualdirectory
-- module: win_iis_webapplication
-- module: win_iis_webapppool
-- module: win_iis_website
-author:
- - Noah Sparks (@nwsparks)
- - Henrik Wallström (@henrikwallstrom)
-'''
-
-EXAMPLES = r'''
-- name: Add a HTTP binding on port 9090
- win_iis_webbinding:
- name: Default Web Site
- port: 9090
- state: present
-
-- name: Remove the HTTP binding on port 9090
- win_iis_webbinding:
- name: Default Web Site
- port: 9090
- state: absent
-
-- name: Remove the default http binding
- win_iis_webbinding:
- name: Default Web Site
- port: 80
- ip: '*'
- state: absent
-
-- name: Add a HTTPS binding
- win_iis_webbinding:
- name: Default Web Site
- protocol: https
- port: 443
- ip: 127.0.0.1
- certificate_hash: B0D0FA8408FC67B230338FCA584D03792DA73F4C
- state: present
-
-- name: Add a HTTPS binding with host header and SNI enabled
- win_iis_webbinding:
- name: Default Web Site
- protocol: https
- port: 443
- host_header: test.com
- ssl_flags: 1
- certificate_hash: D1A3AF8988FD32D1A3AF8988FD323792DA73F4C
- state: present
-'''
-
-RETURN = r'''
-website_state:
- description:
- - The state of the website being targetted
- - Can be helpful in case you accidentally cause a binding collision
- which can result in the targetted site being stopped
- returned: always
- type: str
- sample: "Started"
- version_added: "2.5"
-operation_type:
- description:
- - The type of operation performed
- - Can be removed, updated, matched, or added
- returned: on success
- type: str
- sample: "removed"
- version_added: "2.5"
-binding_info:
- description:
- - Information on the binding being manipulated
- returned: on success
- type: dict
- sample: |-
- "binding_info": {
- "bindingInformation": "127.0.0.1:443:",
- "certificateHash": "FF3910CE089397F1B5A77EB7BAFDD8F44CDE77DD",
- "certificateStoreName": "MY",
- "hostheader": "",
- "ip": "127.0.0.1",
- "port": 443,
- "protocol": "https",
- "sslFlags": "not supported"
- }
- version_added: "2.5"
-'''
diff --git a/lib/ansible/modules/windows/win_iis_website.ps1 b/lib/ansible/modules/windows/win_iis_website.ps1
deleted file mode 100644
index e7b6cab8bf..0000000000
--- a/lib/ansible/modules/windows/win_iis_website.ps1
+++ /dev/null
@@ -1,180 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-$params = Parse-Args $args
-$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
-$application_pool = Get-AnsibleParam -obj $params -name "application_pool" -type "str"
-$physical_path = Get-AnsibleParam -obj $params -name "physical_path" -type "str"
-$site_id = Get-AnsibleParam -obj $params -name "site_id" -type "str"
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -validateset "absent","restarted","started","stopped"
-
-# Binding Parameters
-$bind_port = Get-AnsibleParam -obj $params -name "port" -type "int"
-$bind_ip = Get-AnsibleParam -obj $params -name "ip" -type "str"
-$bind_hostname = Get-AnsibleParam -obj $params -name "hostname" -type "str"
-
-# Custom site Parameters from string where properties
-# are separated by a pipe and property name/values by colon.
-# Ex. "foo:1|bar:2"
-$parameters = Get-AnsibleParam -obj $params -name "parameters" -type "str"
-if($null -ne $parameters) {
- $parameters = @($parameters -split '\|' | ForEach-Object {
- return ,($_ -split "\:", 2);
- })
-}
-
-
-# Ensure WebAdministration module is loaded
-if ($null -eq (Get-Module "WebAdministration" -ErrorAction SilentlyContinue)) {
- Import-Module WebAdministration
-}
-
-# Result
-$result = @{
- site = @{}
- changed = $false
-}
-
-# Site info
-$site = Get-Website | Where-Object { $_.Name -eq $name }
-
-Try {
- # Add site
- If(($state -ne 'absent') -and (-not $site)) {
- If (-not $physical_path) {
- Fail-Json -obj $result -message "missing required arguments: physical_path"
- }
- ElseIf (-not (Test-Path $physical_path)) {
- Fail-Json -obj $result -message "specified folder must already exist: physical_path"
- }
-
- $site_parameters = @{
- Name = $name
- PhysicalPath = $physical_path
- }
-
- If ($application_pool) {
- $site_parameters.ApplicationPool = $application_pool
- }
-
- If ($site_id) {
- $site_parameters.ID = $site_id
- }
-
- If ($bind_port) {
- $site_parameters.Port = $bind_port
- }
-
- If ($bind_ip) {
- $site_parameters.IPAddress = $bind_ip
- }
-
- If ($bind_hostname) {
- $site_parameters.HostHeader = $bind_hostname
- }
-
- # Fix for error "New-Item : Index was outside the bounds of the array."
- # This is a bug in the New-WebSite commandlet. Apparently there must be at least one site configured in IIS otherwise New-WebSite crashes.
- # For more details, see http://stackoverflow.com/questions/3573889/ps-c-new-website-blah-throws-index-was-outside-the-bounds-of-the-array
- $sites_list = get-childitem -Path IIS:\sites
- if ($null -eq $sites_list) {
- if ($site_id) {
- $site_parameters.ID = $site_id
- } else {
- $site_parameters.ID = 1
- }
- }
-
- $site = New-Website @site_parameters -Force
- $result.changed = $true
- }
-
- # Remove site
- If ($state -eq 'absent' -and $site) {
- $site = Remove-Website -Name $name
- $result.changed = $true
- }
-
- $site = Get-Website | Where-Object { $_.Name -eq $name }
- If($site) {
- # Change Physical Path if needed
- if($physical_path) {
- If (-not (Test-Path $physical_path)) {
- Fail-Json -obj $result -message "specified folder must already exist: physical_path"
- }
-
- $folder = Get-Item $physical_path
- If($folder.FullName -ne $site.PhysicalPath) {
- Set-ItemProperty "IIS:\Sites\$($site.Name)" -name physicalPath -value $folder.FullName
- $result.changed = $true
- }
- }
-
- # Change Application Pool if needed
- if($application_pool) {
- If($application_pool -ne $site.applicationPool) {
- Set-ItemProperty "IIS:\Sites\$($site.Name)" -name applicationPool -value $application_pool
- $result.changed = $true
- }
- }
-
- # Set properties
- if($parameters) {
- $parameters | ForEach-Object {
- $property_value = Get-ItemProperty "IIS:\Sites\$($site.Name)" $_[0]
-
- switch ($property_value.GetType().Name)
- {
- "ConfigurationAttribute" { $parameter_value = $property_value.value }
- "String" { $parameter_value = $property_value }
- }
-
- if((-not $parameter_value) -or ($parameter_value) -ne $_[1]) {
- Set-ItemProperty -LiteralPath "IIS:\Sites\$($site.Name)" $_[0] $_[1]
- $result.changed = $true
- }
- }
- }
-
- # Set run state
- if ((($state -eq 'stopped') -or ($state -eq 'restarted')) -and ($site.State -eq 'Started'))
- {
- Stop-Website -Name $name -ErrorAction Stop
- $result.changed = $true
- }
- if ((($state -eq 'started') -and ($site.State -eq 'Stopped')) -or ($state -eq 'restarted'))
- {
- Start-Website -Name $name -ErrorAction Stop
- $result.changed = $true
- }
- }
-}
-Catch
-{
- Fail-Json -obj $result -message $_.Exception.Message
-}
-
-if ($state -ne 'absent')
-{
- $site = Get-Website | Where-Object { $_.Name -eq $name }
-}
-
-if ($site)
-{
- $result.site = @{
- Name = $site.Name
- ID = $site.ID
- State = $site.State
- PhysicalPath = $site.PhysicalPath
- ApplicationPool = $site.applicationPool
- Bindings = @($site.Bindings.Collection | ForEach-Object { $_.BindingInformation })
- }
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_iis_website.py b/lib/ansible/modules/windows/win_iis_website.py
deleted file mode 100644
index c059b4171c..0000000000
--- a/lib/ansible/modules/windows/win_iis_website.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_iis_website
-version_added: "2.0"
-short_description: Configures a IIS Web site
-description:
- - Creates, Removes and configures a IIS Web site.
-options:
- name:
- description:
- - Names of web site.
- type: str
- required: yes
- site_id:
- description:
- - Explicitly set the IIS numeric ID for a site.
- - Note that this value cannot be changed after the website has been created.
- type: str
- version_added: "2.1"
- state:
- description:
- - State of the web site
- type: str
- choices: [ absent, started, stopped, restarted ]
- physical_path:
- description:
- - The physical path on the remote host to use for the new site.
- - The specified folder must already exist.
- type: str
- application_pool:
- description:
- - The application pool in which the new site executes.
- type: str
- port:
- description:
- - The port to bind to / use for the new site.
- type: int
- ip:
- description:
- - The IP address to bind to / use for the new site.
- type: str
- hostname:
- description:
- - The host header to bind to / use for the new site.
- type: str
- ssl:
- description:
- - Enables HTTPS binding on the site..
- type: str
- parameters:
- description:
- - Custom site Parameters from string where properties are separated by a pipe and property name/values by colon Ex. "foo:1|bar:2"
- type: str
-seealso:
-- module: win_iis_virtualdirectory
-- module: win_iis_webapplication
-- module: win_iis_webapppool
-- module: win_iis_webbinding
-author:
-- Henrik Wallström (@henrikwallstrom)
-'''
-
-EXAMPLES = r'''
-
-# Start a website
-
-- name: Acme IIS site
- win_iis_website:
- name: Acme
- state: started
- port: 80
- ip: 127.0.0.1
- hostname: acme.local
- application_pool: acme
- physical_path: C:\sites\acme
- parameters: logfile.directory:C:\sites\logs
- register: website
-
-# Remove Default Web Site and the standard port 80 binding
-- name: Remove Default Web Site
- win_iis_website:
- name: "Default Web Site"
- state: absent
-
-# Some commandline examples:
-
-# This return information about an existing host
-# $ ansible -i vagrant-inventory -m win_iis_website -a "name='Default Web Site'" window
-# host | success >> {
-# "changed": false,
-# "site": {
-# "ApplicationPool": "DefaultAppPool",
-# "Bindings": [
-# "*:80:"
-# ],
-# "ID": 1,
-# "Name": "Default Web Site",
-# "PhysicalPath": "%SystemDrive%\\inetpub\\wwwroot",
-# "State": "Stopped"
-# }
-# }
-
-# This stops an existing site.
-# $ ansible -i hosts -m win_iis_website -a "name='Default Web Site' state=stopped" host
-
-# This creates a new site.
-# $ ansible -i hosts -m win_iis_website -a "name=acme physical_path=C:\\sites\\acme" host
-
-# Change logfile.
-# $ ansible -i hosts -m win_iis_website -a "name=acme physical_path=C:\\sites\\acme" host
-'''
diff --git a/lib/ansible/modules/windows/win_inet_proxy.ps1 b/lib/ansible/modules/windows/win_inet_proxy.ps1
deleted file mode 100644
index 3b0420f648..0000000000
--- a/lib/ansible/modules/windows/win_inet_proxy.ps1
+++ /dev/null
@@ -1,495 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.AddType
-
-$spec = @{
- options = @{
- auto_detect = @{ type = "bool"; default = $true }
- auto_config_url = @{ type = "str" }
- proxy = @{ type = "raw" }
- bypass = @{ type = "list" }
- connection = @{ type = "str" }
- }
- required_by = @{
- bypass = @("proxy")
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$auto_detect = $module.Params.auto_detect
-$auto_config_url = $module.Params.auto_config_url
-$proxy = $module.Params.proxy
-$bypass = $module.Params.bypass
-$connection = $module.Params.connection
-
-# Parse the raw value, it should be a Dictionary or String
-if ($proxy -is [System.Collections.IDictionary]) {
- $valid_keys = [System.Collections.Generic.List`1[String]]@("http", "https", "ftp", "socks")
- # Check to make sure we don't have any invalid keys in the dict
- $invalid_keys = [System.Collections.Generic.List`1[String]]@()
- foreach ($k in $proxy.Keys) {
- if ($k -notin $valid_keys) {
- $invalid_keys.Add($k)
- }
- }
-
- if ($invalid_keys.Count -gt 0) {
- $invalid_keys = $invalid_keys | Sort-Object # So our test assertion doesn't fail due to random ordering
- $module.FailJson("Invalid keys found in proxy: $($invalid_keys -join ', '). Valid keys are $($valid_keys -join ', ').")
- }
-
- # Build the proxy string in the form 'protocol=host;', the order of valid_keys is also important
- $proxy_list = [System.Collections.Generic.List`1[String]]@()
- foreach ($k in $valid_keys) {
- if ($proxy.ContainsKey($k)) {
- $proxy_list.Add("$k=$($proxy.$k)")
- }
- }
- $proxy = $proxy_list -join ";"
-} elseif ($null -ne $proxy) {
- $proxy = $proxy.ToString()
-}
-
-if ($bypass) {
- if ([System.String]::IsNullOrEmpty($proxy)) {
- $module.FailJson("missing parameter(s) required by ''bypass'': proxy")
- }
- $bypass = $bypass -join ';'
-}
-
-$win_inet_invoke = @'
-using Microsoft.Win32.SafeHandles;
-using System;
-using System.Collections.Generic;
-using System.Runtime.ConstrainedExecution;
-using System.Runtime.InteropServices;
-
-namespace Ansible.WinINetProxy
-{
- internal class NativeHelpers
- {
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public class INTERNET_PER_CONN_OPTION_LISTW : IDisposable
- {
- public UInt32 dwSize;
- public IntPtr pszConnection;
- public UInt32 dwOptionCount;
- public UInt32 dwOptionError;
- public IntPtr pOptions;
-
- public INTERNET_PER_CONN_OPTION_LISTW()
- {
- dwSize = (UInt32)Marshal.SizeOf(this);
- }
-
- public void Dispose()
- {
- if (pszConnection != IntPtr.Zero)
- Marshal.FreeHGlobal(pszConnection);
- if (pOptions != IntPtr.Zero)
- Marshal.FreeHGlobal(pOptions);
- GC.SuppressFinalize(this);
- }
- ~INTERNET_PER_CONN_OPTION_LISTW() { this.Dispose(); }
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public class INTERNET_PER_CONN_OPTIONW : IDisposable
- {
- public INTERNET_PER_CONN_OPTION dwOption;
- public ValueUnion Value;
-
- [StructLayout(LayoutKind.Explicit)]
- public class ValueUnion
- {
- [FieldOffset(0)]
- public UInt32 dwValue;
-
- [FieldOffset(0)]
- public IntPtr pszValue;
-
- [FieldOffset(0)]
- public System.Runtime.InteropServices.ComTypes.FILETIME ftValue;
- }
-
- public void Dispose()
- {
- // We can't just check if Value.pszValue is not IntPtr.Zero as the union means it could be set even
- // when the value is a UInt32 or FILETIME. We check against a known string option type and only free
- // the value in those cases.
- List<INTERNET_PER_CONN_OPTION> stringOptions = new List<INTERNET_PER_CONN_OPTION>
- {
- { INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_AUTOCONFIG_URL },
- { INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_BYPASS },
- { INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_SERVER }
- };
- if (Value != null && Value.pszValue != IntPtr.Zero && stringOptions.Contains(dwOption))
- Marshal.FreeHGlobal(Value.pszValue);
- GC.SuppressFinalize(this);
- }
- ~INTERNET_PER_CONN_OPTIONW() { this.Dispose(); }
- }
-
- public enum INTERNET_OPTION : uint
- {
- INTERNET_OPTION_PER_CONNECTION_OPTION = 75,
- INTERNET_OPTION_PROXY_SETTINGS_CHANGED = 95,
- }
-
- public enum INTERNET_PER_CONN_OPTION : uint
- {
- INTERNET_PER_CONN_FLAGS = 1,
- INTERNET_PER_CONN_PROXY_SERVER = 2,
- INTERNET_PER_CONN_PROXY_BYPASS = 3,
- INTERNET_PER_CONN_AUTOCONFIG_URL = 4,
- INTERNET_PER_CONN_AUTODISCOVERY_FLAGS = 5,
- INTERNET_PER_CONN_FLAGS_UI = 10, // IE8+ - Included with Windows 7 and Server 2008 R2
- }
-
- [Flags]
- public enum PER_CONN_FLAGS : uint
- {
- PROXY_TYPE_DIRECT = 0x00000001,
- PROXY_TYPE_PROXY = 0x00000002,
- PROXY_TYPE_AUTO_PROXY_URL = 0x00000004,
- PROXY_TYPE_AUTO_DETECT = 0x00000008,
- }
- }
-
- internal class NativeMethods
- {
- [DllImport("Wininet.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool InternetQueryOptionW(
- IntPtr hInternet,
- NativeHelpers.INTERNET_OPTION dwOption,
- SafeMemoryBuffer lpBuffer,
- ref UInt32 lpdwBufferLength);
-
- [DllImport("Wininet.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool InternetSetOptionW(
- IntPtr hInternet,
- NativeHelpers.INTERNET_OPTION dwOption,
- SafeMemoryBuffer lpBuffer,
- UInt32 dwBufferLength);
-
- [DllImport("Rasapi32.dll", CharSet = CharSet.Unicode)]
- public static extern UInt32 RasValidateEntryNameW(
- string lpszPhonebook,
- string lpszEntry);
- }
-
- internal class SafeMemoryBuffer : SafeHandleZeroOrMinusOneIsInvalid
- {
- public SafeMemoryBuffer() : base(true) { }
- public SafeMemoryBuffer(int cb) : base(true)
- {
- base.SetHandle(Marshal.AllocHGlobal(cb));
- }
- public SafeMemoryBuffer(IntPtr handle) : base(true)
- {
- base.SetHandle(handle);
- }
-
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
- protected override bool ReleaseHandle()
- {
- Marshal.FreeHGlobal(handle);
- return true;
- }
- }
-
- public class Win32Exception : System.ComponentModel.Win32Exception
- {
- private string _msg;
-
- public Win32Exception(string message) : this(Marshal.GetLastWin32Error(), message) { }
- public Win32Exception(int errorCode, string message) : base(errorCode)
- {
- _msg = String.Format("{0} ({1}, Win32ErrorCode {2})", message, base.Message, errorCode);
- }
-
- public override string Message { get { return _msg; } }
- public static explicit operator Win32Exception(string message) { return new Win32Exception(message); }
- }
-
- public class WinINetProxy
- {
- private string Connection;
-
- public string AutoConfigUrl;
- public bool AutoDetect;
- public string Proxy;
- public string ProxyBypass;
-
- public WinINetProxy(string connection)
- {
- Connection = connection;
- Refresh();
- }
-
- public static bool IsValidConnection(string name)
- {
- // RasValidateEntryName is used to verify is a name can be a valid phonebook entry. It returns 0 if no
- // entry exists and 183 if it already exists. We just need to check if it returns 183 to verify the
- // connection name.
- return NativeMethods.RasValidateEntryNameW(null, name) == 183;
- }
-
- public void Refresh()
- {
- using (var connFlags = CreateConnOption(NativeHelpers.INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_FLAGS_UI))
- using (var autoConfigUrl = CreateConnOption(NativeHelpers.INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_AUTOCONFIG_URL))
- using (var server = CreateConnOption(NativeHelpers.INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_SERVER))
- using (var bypass = CreateConnOption(NativeHelpers.INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_BYPASS))
- {
- NativeHelpers.INTERNET_PER_CONN_OPTIONW[] options = new NativeHelpers.INTERNET_PER_CONN_OPTIONW[]
- {
- connFlags, autoConfigUrl, server, bypass
- };
-
- try
- {
- QueryOption(options, Connection);
- }
- catch (Win32Exception e)
- {
- if (e.NativeErrorCode == 87) // ERROR_INVALID_PARAMETER
- {
- // INTERNET_PER_CONN_FLAGS_UI only works for IE8+, try the fallback in case we are still working
- // with an ancient version.
- connFlags.dwOption = NativeHelpers.INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_FLAGS;
- QueryOption(options, Connection);
- }
- else
- throw;
- }
-
- NativeHelpers.PER_CONN_FLAGS flags = (NativeHelpers.PER_CONN_FLAGS)connFlags.Value.dwValue;
-
- AutoConfigUrl = flags.HasFlag(NativeHelpers.PER_CONN_FLAGS.PROXY_TYPE_AUTO_PROXY_URL)
- ? Marshal.PtrToStringUni(autoConfigUrl.Value.pszValue) : null;
- AutoDetect = flags.HasFlag(NativeHelpers.PER_CONN_FLAGS.PROXY_TYPE_AUTO_DETECT);
- if (flags.HasFlag(NativeHelpers.PER_CONN_FLAGS.PROXY_TYPE_PROXY))
- {
- Proxy = Marshal.PtrToStringUni(server.Value.pszValue);
- ProxyBypass = Marshal.PtrToStringUni(bypass.Value.pszValue);
- }
- else
- {
- Proxy = null;
- ProxyBypass = null;
- }
- }
- }
-
- public void Set()
- {
- using (var connFlags = CreateConnOption(NativeHelpers.INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_FLAGS_UI))
- using (var autoConfigUrl = CreateConnOption(NativeHelpers.INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_AUTOCONFIG_URL))
- using (var server = CreateConnOption(NativeHelpers.INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_SERVER))
- using (var bypass = CreateConnOption(NativeHelpers.INTERNET_PER_CONN_OPTION.INTERNET_PER_CONN_PROXY_BYPASS))
- {
- List<NativeHelpers.INTERNET_PER_CONN_OPTIONW> options = new List<NativeHelpers.INTERNET_PER_CONN_OPTIONW>();
-
- // PROXY_TYPE_DIRECT seems to always be set, need to verify
- NativeHelpers.PER_CONN_FLAGS flags = NativeHelpers.PER_CONN_FLAGS.PROXY_TYPE_DIRECT;
- if (AutoDetect)
- flags |= NativeHelpers.PER_CONN_FLAGS.PROXY_TYPE_AUTO_DETECT;
-
- if (!String.IsNullOrEmpty(AutoConfigUrl))
- {
- flags |= NativeHelpers.PER_CONN_FLAGS.PROXY_TYPE_AUTO_PROXY_URL;
- autoConfigUrl.Value.pszValue = Marshal.StringToHGlobalUni(AutoConfigUrl);
- }
- options.Add(autoConfigUrl);
-
- if (!String.IsNullOrEmpty(Proxy))
- {
- flags |= NativeHelpers.PER_CONN_FLAGS.PROXY_TYPE_PROXY;
- server.Value.pszValue = Marshal.StringToHGlobalUni(Proxy);
- }
- options.Add(server);
-
- if (!String.IsNullOrEmpty(ProxyBypass))
- bypass.Value.pszValue = Marshal.StringToHGlobalUni(ProxyBypass);
- options.Add(bypass);
-
- connFlags.Value.dwValue = (UInt32)flags;
- options.Add(connFlags);
-
- SetOption(options.ToArray(), Connection);
-
- // Tell IE that the proxy settings have been changed.
- if (!NativeMethods.InternetSetOptionW(
- IntPtr.Zero,
- NativeHelpers.INTERNET_OPTION.INTERNET_OPTION_PROXY_SETTINGS_CHANGED,
- new SafeMemoryBuffer(IntPtr.Zero),
- 0))
- {
- throw new Win32Exception("InternetSetOptionW(INTERNET_OPTION_PROXY_SETTINGS_CHANGED) failed");
- }
- }
- }
-
- internal static NativeHelpers.INTERNET_PER_CONN_OPTIONW CreateConnOption(NativeHelpers.INTERNET_PER_CONN_OPTION option)
- {
- return new NativeHelpers.INTERNET_PER_CONN_OPTIONW
- {
- dwOption = option,
- Value = new NativeHelpers.INTERNET_PER_CONN_OPTIONW.ValueUnion(),
- };
- }
-
- internal static void QueryOption(NativeHelpers.INTERNET_PER_CONN_OPTIONW[] options, string connection = null)
- {
- using (NativeHelpers.INTERNET_PER_CONN_OPTION_LISTW optionList = new NativeHelpers.INTERNET_PER_CONN_OPTION_LISTW())
- using (SafeMemoryBuffer optionListPtr = MarshalOptionList(optionList, options, connection))
- {
- UInt32 bufferSize = optionList.dwSize;
- if (!NativeMethods.InternetQueryOptionW(
- IntPtr.Zero,
- NativeHelpers.INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION,
- optionListPtr,
- ref bufferSize))
- {
- throw new Win32Exception("InternetQueryOptionW(INTERNET_OPTION_PER_CONNECTION_OPTION) failed");
- }
-
- for (int i = 0; i < options.Length; i++)
- {
- IntPtr opt = IntPtr.Add(optionList.pOptions, i * Marshal.SizeOf(typeof(NativeHelpers.INTERNET_PER_CONN_OPTIONW)));
- NativeHelpers.INTERNET_PER_CONN_OPTIONW option = (NativeHelpers.INTERNET_PER_CONN_OPTIONW)Marshal.PtrToStructure(opt,
- typeof(NativeHelpers.INTERNET_PER_CONN_OPTIONW));
- options[i].Value = option.Value;
- option.Value = null; // Stops the GC from freeing the same memory twice
- }
- }
- }
-
- internal static void SetOption(NativeHelpers.INTERNET_PER_CONN_OPTIONW[] options, string connection = null)
- {
- using (NativeHelpers.INTERNET_PER_CONN_OPTION_LISTW optionList = new NativeHelpers.INTERNET_PER_CONN_OPTION_LISTW())
- using (SafeMemoryBuffer optionListPtr = MarshalOptionList(optionList, options, connection))
- {
- if (!NativeMethods.InternetSetOptionW(
- IntPtr.Zero,
- NativeHelpers.INTERNET_OPTION.INTERNET_OPTION_PER_CONNECTION_OPTION,
- optionListPtr,
- optionList.dwSize))
- {
- throw new Win32Exception("InternetSetOptionW(INTERNET_OPTION_PER_CONNECTION_OPTION) failed");
- }
- }
- }
-
- internal static SafeMemoryBuffer MarshalOptionList(NativeHelpers.INTERNET_PER_CONN_OPTION_LISTW optionList,
- NativeHelpers.INTERNET_PER_CONN_OPTIONW[] options, string connection)
- {
- optionList.pszConnection = Marshal.StringToHGlobalUni(connection);
- optionList.dwOptionCount = (UInt32)options.Length;
-
- int optionSize = Marshal.SizeOf(typeof(NativeHelpers.INTERNET_PER_CONN_OPTIONW));
- optionList.pOptions = Marshal.AllocHGlobal(optionSize * options.Length);
- for (int i = 0; i < options.Length; i++)
- {
- IntPtr option = IntPtr.Add(optionList.pOptions, i * optionSize);
- Marshal.StructureToPtr(options[i], option, false);
- }
-
- SafeMemoryBuffer optionListPtr = new SafeMemoryBuffer((int)optionList.dwSize);
- Marshal.StructureToPtr(optionList, optionListPtr.DangerousGetHandle(), false);
- return optionListPtr;
- }
- }
-}
-'@
-Add-CSharpType -References $win_inet_invoke -AnsibleModule $module
-
-# We need to validate the connection because WinINet will just silently continue even if the connection does not
-# already exist.
-if ($null -ne $connection -and -not [Ansible.WinINetProxy.WinINetProxy]::IsValidConnection($connection)) {
- $module.FailJson("The connection '$connection' does not exist.")
-}
-
-$actual_proxy = New-Object -TypeName Ansible.WinINetProxy.WinINetProxy -ArgumentList @(,$connection)
-$module.Diff.before = @{
- auto_config_url = $actual_proxy.AutoConfigUrl
- auto_detect = $actual_proxy.AutoDetect
- bypass = $actual_proxy.ProxyBypass
- server = $actual_proxy.Proxy
-}
-
-# Make sure an empty string is converted to $null for easier comparisons
-if ([String]::IsNullOrEmpty($auto_config_url)) {
- $auto_config_url = $null
-}
-if ([String]::IsNullOrEmpty($proxy)) {
- $proxy = $null
-}
-if ([String]::IsNullOrEmpty($bypass)) {
- $bypass = $null
-}
-
-# Record the original values in case we need to revert on a failure
-$previous_auto_config_url = $actual_proxy.AutoConfigUrl
-$previous_auto_detect = $actual_proxy.AutoDetect
-$previous_proxy = $actual_proxy.Proxy
-$previous_bypass = $actual_proxy.ProxyBypass
-
-$changed = $false
-if ($auto_config_url -ne $previous_auto_config_url) {
- $actual_proxy.AutoConfigUrl = $auto_config_url
- $changed = $true
-}
-
-if ($auto_detect -ne $previous_auto_detect) {
- $actual_proxy.AutoDetect = $auto_detect
- $changed = $true
-}
-
-if ($proxy -ne $previous_proxy) {
- $actual_proxy.Proxy = $proxy
- $changed = $true
-}
-
-if ($bypass -ne $previous_bypass) {
- $actual_proxy.ProxyBypass = $bypass
- $changed = $true
-}
-
-if ($changed -and -not $module.CheckMode) {
- $actual_proxy.Set()
-
- # Validate that the change was made correctly and revert if it wasn't. THe Set() method won't fail on invalid
- # values so we need to check again to make sure all was good
- $actual_proxy.Refresh()
- if ($actual_proxy.AutoConfigUrl -ne $auto_config_url -or
- $actual_proxy.AutoDetect -ne $auto_detect -or
- $actual_proxy.Proxy -ne $proxy -or
- $actual_proxy.ProxyBypass -ne $bypass) {
-
- $actual_proxy.AutoConfigUrl = $previous_auto_config_url
- $actual_proxy.AutoDetect = $previous_auto_detect
- $actual_proxy.Proxy = $previous_proxy
- $actual_proxy.ProxyBypass = $previous_bypass
- $actual_proxy.Set()
-
- $module.FailJson("Unknown error when trying to set auto_config_url '$auto_config_url', proxy '$proxy', or bypass '$bypass'")
- }
-}
-$module.Result.changed = $changed
-
-$module.Diff.after = @{
- auto_config_url = $auto_config_url
- auto_detect = $auto_detect
- bypass = $bypass
- proxy = $proxy
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_inet_proxy.py b/lib/ansible/modules/windows/win_inet_proxy.py
deleted file mode 100644
index 8a3449f399..0000000000
--- a/lib/ansible/modules/windows/win_inet_proxy.py
+++ /dev/null
@@ -1,173 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2019, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_inet_proxy
-version_added: '2.8'
-short_description: Manages proxy settings for WinINet and Internet Explorer
-description:
-- Used to set or remove proxy settings for Windows INet which includes Internet
- Explorer.
-- WinINet is a framework used by interactive applications to submit web
- requests through.
-- The proxy settings can also be used by other applications like Firefox,
- Chrome, and others but there is no definitive list.
-options:
- auto_detect:
- description:
- - Whether to configure WinINet to automatically detect proxy settings
- through Web Proxy Auto-Detection C(WPAD).
- - This corresponds to the checkbox I(Automatically detect settings) in the
- connection settings window.
- default: yes
- type: bool
- auto_config_url:
- description:
- - The URL of a proxy configuration script.
- - Proxy configuration scripts are typically JavaScript files with the
- C(.pac) extension that implement the C(FindProxyForURL(url, host)
- function.
- - Omit, set to null or an empty string to remove the auto config URL.
- - This corresponds to the checkbox I(Use automatic configuration script) in
- the connection settings window.
- type: str
- bypass:
- description:
- - A list of hosts that will bypass the set proxy when being accessed.
- - Use C(<local>) to match hostnames that are not fully qualified domain
- names. This is useful when needing to connect to intranet sites using
- just the hostname. If defined, this should be the last entry in the
- bypass list.
- - Use C(<-loopback>) to stop automatically bypassing the proxy when
- connecting through any loopback address like C(127.0.0.1), C(localhost),
- or the local hostname.
- - Omit, set to null or an empty string/list to remove the bypass list.
- - If this is set then I(proxy) must also be set.
- type: list
- connection:
- description:
- - The name of the IE connection to set the proxy settings for.
- - These are the connections under the I(Dial-up and Virtual Private Network)
- header in the IE settings.
- - When omitted, the default LAN connection is used.
- type: str
- proxy:
- description:
- - A string or dict that specifies the proxy to be set.
- - If setting a string, should be in the form C(hostname), C(hostname:port),
- or C(protocol=hostname:port).
- - If the port is undefined, the default port for the protocol in use is
- used.
- - If setting a dict, the keys should be the protocol and the values should
- be the hostname and/or port for that protocol.
- - Valid protocols are C(http), C(https), C(ftp), and C(socks).
- - Omit, set to null or an empty string to remove the proxy settings.
-notes:
-- This is not the same as the proxy settings set in WinHTTP through the
- C(netsh) command. Use the M(win_http_proxy) module to manage that instead.
-- These settings are by default set per user and not system wide. A registry
- property must be set independently from this module if you wish to apply the
- proxy for all users. See examples for more detail.
-- If per user proxy settings are desired, use I(become) to become any local
- user on the host. No password is needed to be set for this to work.
-- If the proxy requires authentication, set the credentials using the
- M(win_credential) module. This requires I(become) to be used so the
- credential store can be accessed.
-seealso:
-- module: win_http_proxy
-- module: win_credential
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-# This should be set before running the win_inet_proxy module
-- name: Configure IE proxy settings to apply to all users
- win_regedit:
- path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings
- name: ProxySettingsPerUser
- data: 0
- type: dword
- state: present
-
-# This should be set before running the win_inet_proxy module
-- name: Configure IE proxy settings to apply per user
- win_regedit:
- path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings
- name: ProxySettingsPerUser
- data: 1
- type: dword
- state: present
-
-- name: Configure IE proxy to use auto detected settings without an explicit proxy
- win_inet_proxy:
- auto_detect: yes
-
-- name: Configure IE proxy to use auto detected settings with a configuration script
- win_inet_proxy:
- auto_detect: yes
- auto_config_url: http://proxy.ansible.com/proxy.pac
-
-- name: Configure IE to use explicit proxy host
- win_inet_proxy:
- auto_detect: yes
- proxy: ansible.proxy
-
-- name: Configure IE to use explicit proxy host with port and without auto detection
- win_inet_proxy:
- auto_detect: no
- proxy: ansible.proxy:8080
-
-- name: Configure IE to use a specific proxy per protocol
- win_inet_proxy:
- proxy:
- http: ansible.proxy:8080
- https: ansible.proxy:8443
-
-- name: Configure IE to use a specific proxy per protocol using a string
- win_inet_proxy:
- proxy: http=ansible.proxy:8080;https=ansible.proxy:8443
-
-- name: Set a proxy with a bypass list
- win_inet_proxy:
- proxy: ansible.proxy
- bypass:
- - server1
- - server2
- - <-loopback>
- - <local>
-
-- name: Remove any explicit proxies that are set
- win_inet_proxy:
- proxy: ''
- bypass: ''
-
-# This should be done after setting the IE proxy with win_inet_proxy
-- name: Import IE proxy configuration to WinHTTP
- win_http_proxy:
- source: ie
-
-# Explicit credentials can only be set per user and require become to work
-- name: Set credential to use for proxy auth
- win_credential:
- name: ansible.proxy # The name should be the FQDN of the proxy host
- type: generic_password
- username: proxyuser
- secret: proxypass
- state: present
- become: yes
- become_user: '{{ ansible_user }}'
- become_method: runas
-'''
-
-RETURN = r'''
-#
-'''
diff --git a/lib/ansible/modules/windows/win_initialize_disk.ps1 b/lib/ansible/modules/windows/win_initialize_disk.ps1
deleted file mode 100644
index 556c74b372..0000000000
--- a/lib/ansible/modules/windows/win_initialize_disk.ps1
+++ /dev/null
@@ -1,151 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Brant Evans <bevans@redhat.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#AnsibleRequires -OSVersion 6.2
-
-Set-StrictMode -Version 2
-
-$spec = @{
- options = @{
- disk_number = @{ type = "int" }
- uniqueid = @{ type = "str" }
- path = @{ type = "str" }
- style = @{ type = "str"; choices = "gpt", "mbr"; default = "gpt" }
- online = @{ type = "bool"; default = $true }
- force = @{ type = "bool"; default = $false }
- }
- mutually_exclusive = @(
- ,@('disk_number', 'uniqueid', 'path')
- )
- required_one_of = @(
- ,@('disk_number', 'uniqueid', 'path')
- )
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$disk_number = $module.Params.disk_number
-$uniqueid = $module.Params.uniqueid
-$path = $module.Params.path
-$partition_style = $module.Params.style
-$bring_online = $module.Params.online
-$force_init = $module.Params.force
-
-function Get-AnsibleDisk {
- param(
- $DiskNumber,
- $UniqueId,
- $Path
- )
-
- if ($null -ne $DiskNumber) {
- try {
- $disk = Get-Disk -Number $DiskNumber
- } catch {
- $module.FailJson("There was an error retrieving the disk using disk_number $($DiskNumber): $($_.Exception.Message)")
- }
- } elseif ($null -ne $UniqueId) {
- try {
- $disk = Get-Disk -UniqueId $UniqueId
- } catch {
- $module.FailJson("There was an error retrieving the disk using id $($UniqueId): $($_.Exception.Message)")
- }
- } elseif ($null -ne $Path) {
- try {
- $disk = Get-Disk -Path $Path
- } catch {
- $module.FailJson("There was an error retrieving the disk using path $($Path): $($_.Exception.Message)")
- }
- } else {
- $module.FailJson("Unable to retrieve disk: disk_number, id, or path was not specified")
- }
-
- return $disk
-}
-
-function Initialize-AnsibleDisk {
- param(
- $AnsibleDisk,
- $PartitionStyle
- )
-
- if ($AnsibleDisk.IsReadOnly) {
- $module.FailJson("Unable to initialize disk as it is read-only")
- }
-
- $parameters = @{
- Number = $AnsibleDisk.Number
- PartitionStyle = $PartitionStyle
- }
-
- if (-Not $module.CheckMode) {
- Initialize-Disk @parameters -Confirm:$false
- }
-
- $module.Result.changed = $true
-}
-
-function Clear-AnsibleDisk {
- param(
- $AnsibleDisk
- )
-
- $parameters = @{
- Number = $AnsibleDisk.Number
- }
-
- if (-Not $module.CheckMode) {
- Clear-Disk @parameters -RemoveData -RemoveOEM -Confirm:$false
- }
-}
-
-function Set-AnsibleDisk {
- param(
- $AnsibleDisk,
- $BringOnline
- )
-
- $refresh_disk_status = $false
-
- if ($BringOnline) {
- if (-Not $module.CheckMode) {
- if ($AnsibleDisk.IsOffline) {
- Set-Disk -Number $AnsibleDisk.Number -IsOffline:$false
- $refresh_disk_status = $true
- }
-
- if ($AnsibleDisk.IsReadOnly) {
- Set-Disk -Number $AnsibleDisk.Number -IsReadOnly:$false
- $refresh_disk_status = $true
- }
- }
- }
-
- if ($refresh_disk_status) {
- $AnsibleDisk = Get-AnsibleDisk -DiskNumber $AnsibleDisk.Number
- }
-
- return $AnsibleDisk
-}
-
-$ansible_disk = Get-AnsibleDisk -DiskNumber $disk_number -UniqueId $uniqueid -Path $path
-$ansible_part_style = $ansible_disk.PartitionStyle
-
-if ("RAW" -eq $ansible_part_style) {
- $ansible_disk = Set-AnsibleDisk -AnsibleDisk $ansible_disk -BringOnline $bring_online
- Initialize-AnsibleDisk -AnsibleDisk $ansible_disk -PartitionStyle $partition_style
-} else {
- if (($ansible_part_style -ne $partition_style.ToUpper()) -And -Not $force_init) {
- $module.FailJson("Force initialization must be specified since the target partition style: $($partition_style.ToLower()) is different from the current partition style: $($ansible_part_style.ToLower())")
- } elseif ($force_init) {
- $ansible_disk = Set-AnsibleDisk -AnsibleDisk $ansible_disk -BringOnline $bring_online
- Clear-AnsibleDisk -AnsibleDisk $ansible_disk
- Initialize-AnsibleDisk -AnsibleDisk $ansible_disk -PartitionStyle $partition_style
- }
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_initialize_disk.py b/lib/ansible/modules/windows/win_initialize_disk.py
deleted file mode 100644
index 8328bb0294..0000000000
--- a/lib/ansible/modules/windows/win_initialize_disk.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/python
-
-# Copyright: (c) 2019, Brant Evans <bevans@redhat.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import absolute_import, division, print_function
-__metaclass__ = type
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = '''
----
-module: win_initialize_disk
-
-short_description: Initializes disks on Windows Server
-
-version_added: "2.10"
-
-description:
- - "The M(win_initialize_disk) module initializes disks"
-
-options:
- disk_number:
- description:
- - Used to specify the disk number of the disk to be initialized.
- type: int
- uniqueid:
- description:
- - Used to specify the uniqueid of the disk to be initialized.
- type: str
- path:
- description:
- - Used to specify the path to the disk to be initialized.
- type: str
- style:
- description:
- - The partition style to use for the disk. Valid options are mbr or gpt.
- type: str
- choices: [ gpt, mbr ]
- default: gpt
- online:
- description:
- - If the disk is offline and/or readonly update the disk to be online and not readonly.
- type: bool
- default: true
- force:
- description:
- - Specify if initializing should be forced for disks that are already initialized.
- type: bool
-
-notes:
- - One of three parameters (I(disk_number), I(uniqueid), and I(path)) are mandatory to identify the target disk, but
- more than one cannot be specified at the same time.
- - A minimum Operating System Version of Server 2012 or Windows 8 is required to use this module.
- - This module is idempotent if I(force) is not specified.
-
-seealso:
- - module: win_disk_facts
- - module: win_partition
- - module: win_format
-
-author:
- - Brant Evans (@branic)
-'''
-
-EXAMPLES = '''
-- name: Initialize a disk
- win_initialize_disk:
- disk_number: 1
-
-- name: Initialize a disk with an MBR partition style
- win_initialize_disk:
- disk_number: 1
- style: mbr
-
-- name: Forcefully initiallize a disk
- win_initialize_disk:
- disk_number: 2
- force: yes
-'''
-
-RETURN = '''
-#
-'''
diff --git a/lib/ansible/modules/windows/win_lineinfile.ps1 b/lib/ansible/modules/windows/win_lineinfile.ps1
deleted file mode 100644
index 38dd8b8bc0..0000000000
--- a/lib/ansible/modules/windows/win_lineinfile.ps1
+++ /dev/null
@@ -1,450 +0,0 @@
-#!powershell
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.Backup
-
-function WriteLines($outlines, $path, $linesep, $encodingobj, $validate, $check_mode) {
- Try {
- $temppath = [System.IO.Path]::GetTempFileName();
- }
- Catch {
- Fail-Json @{} "Cannot create temporary file! ($($_.Exception.Message))";
- }
- $joined = $outlines -join $linesep;
- [System.IO.File]::WriteAllText($temppath, $joined, $encodingobj);
-
- If ($validate) {
-
- If (-not ($validate -like "*%s*")) {
- Fail-Json @{} "validate must contain %s: $validate";
- }
-
- $validate = $validate.Replace("%s", $temppath);
-
- $parts = [System.Collections.ArrayList] $validate.Split(" ");
- $cmdname = $parts[0];
-
- $cmdargs = $validate.Substring($cmdname.Length + 1);
-
- $process = [Diagnostics.Process]::Start($cmdname, $cmdargs);
- $process.WaitForExit();
-
- If ($process.ExitCode -ne 0) {
- [string] $output = $process.StandardOutput.ReadToEnd();
- [string] $error = $process.StandardError.ReadToEnd();
- Remove-Item $temppath -force;
- Fail-Json @{} "failed to validate $cmdname $cmdargs with error: $output $error";
- }
-
- }
-
- # Commit changes to the path
- $cleanpath = $path.Replace("/", "\");
- Try {
- Copy-Item -Path $temppath -Destination $cleanpath -Force -WhatIf:$check_mode;
- }
- Catch {
- Fail-Json @{} "Cannot write to: $cleanpath ($($_.Exception.Message))";
- }
-
- Try {
- Remove-Item -Path $temppath -Force -WhatIf:$check_mode;
- }
- Catch {
- Fail-Json @{} "Cannot remove temporary file: $temppath ($($_.Exception.Message))";
- }
-
- return $joined;
-
-}
-
-
-# Implement the functionality for state == 'present'
-function Present($path, $regex, $line, $insertafter, $insertbefore, $create, $backup, $backrefs, $validate, $encodingobj, $linesep, $check_mode, $diff_support) {
-
- # Note that we have to clean up the path because ansible wants to treat / and \ as
- # interchangeable in windows pathnames, but .NET framework internals do not support that.
- $cleanpath = $path.Replace("/", "\");
-
- # Check if path exists. If it does not exist, either create it if create == "yes"
- # was specified or fail with a reasonable error message.
- If (-not (Test-Path -LiteralPath $path)) {
- If (-not $create) {
- Fail-Json @{} "Path $path does not exist !";
- }
- # Create new empty file, using the specified encoding to write correct BOM
- [System.IO.File]::WriteAllLines($cleanpath, "", $encodingobj);
- }
-
- # Initialize result information
- $result = @{
- backup = "";
- changed = $false;
- msg = "";
- }
-
- # Read the dest file lines using the indicated encoding into a mutable ArrayList.
- $before = [System.IO.File]::ReadAllLines($cleanpath, $encodingobj)
- If ($null -eq $before) {
- $lines = New-Object System.Collections.ArrayList;
- }
- Else {
- $lines = [System.Collections.ArrayList] $before;
- }
-
- if ($diff_support) {
- $result.diff = @{
- before = $before -join $linesep;
- }
- }
-
- # Compile the regex specified, if provided
- $mre = $null;
- If ($regex) {
- $mre = New-Object Regex $regex, 'Compiled';
- }
-
- # Compile the regex for insertafter or insertbefore, if provided
- $insre = $null;
- If ($insertafter -and $insertafter -ne "BOF" -and $insertafter -ne "EOF") {
- $insre = New-Object Regex $insertafter, 'Compiled';
- }
- ElseIf ($insertbefore -and $insertbefore -ne "BOF") {
- $insre = New-Object Regex $insertbefore, 'Compiled';
- }
-
- # index[0] is the line num where regex has been found
- # index[1] is the line num where insertafter/insertbefore has been found
- $index = -1, -1;
- $lineno = 0;
-
- # The latest match object and matched line
- $matched_line = "";
-
- # Iterate through the lines in the file looking for matches
- Foreach ($cur_line in $lines) {
- If ($regex) {
- $m = $mre.Match($cur_line);
- $match_found = $m.Success;
- If ($match_found) {
- $matched_line = $cur_line;
- }
- }
- Else {
- $match_found = $line -ceq $cur_line;
- }
- If ($match_found) {
- $index[0] = $lineno;
- }
- ElseIf ($insre -and $insre.Match($cur_line).Success) {
- If ($insertafter) {
- $index[1] = $lineno + 1;
- }
- If ($insertbefore) {
- $index[1] = $lineno;
- }
- }
- $lineno = $lineno + 1;
- }
-
- If ($index[0] -ne -1) {
- If ($backrefs) {
- $new_line = [regex]::Replace($matched_line, $regex, $line);
- }
- Else {
- $new_line = $line;
- }
- If ($lines[$index[0]] -cne $new_line) {
- $lines[$index[0]] = $new_line;
- $result.changed = $true;
- $result.msg = "line replaced";
- }
- }
- ElseIf ($backrefs) {
- # No matches - no-op
- }
- ElseIf ($insertbefore -eq "BOF" -or $insertafter -eq "BOF") {
- $lines.Insert(0, $line);
- $result.changed = $true;
- $result.msg = "line added";
- }
- ElseIf ($insertafter -eq "EOF" -or $index[1] -eq -1) {
- $lines.Add($line) > $null;
- $result.changed = $true;
- $result.msg = "line added";
- }
- Else {
- $lines.Insert($index[1], $line);
- $result.changed = $true;
- $result.msg = "line added";
- }
-
- # Write changes to the path if changes were made
- If ($result.changed) {
-
- # Write backup file if backup == "yes"
- If ($backup) {
- $result.backup_file = Backup-File -path $path -WhatIf:$check_mode
- # Ensure backward compatibility (deprecate in future)
- $result.backup = $result.backup_file
- }
-
- $writelines_params = @{
- outlines = $lines
- path = $path
- linesep = $linesep
- encodingobj = $encodingobj
- validate = $validate
- check_mode = $check_mode
- }
- $after = WriteLines @writelines_params;
-
- if ($diff_support) {
- $result.diff.after = $after;
- }
- }
-
- $result.encoding = $encodingobj.WebName;
-
- Exit-Json $result;
-}
-
-
-# Implement the functionality for state == 'absent'
-function Absent($path, $regex, $line, $backup, $validate, $encodingobj, $linesep, $check_mode, $diff_support) {
-
- # Check if path exists. If it does not exist, fail with a reasonable error message.
- If (-not (Test-Path -LiteralPath $path)) {
- Fail-Json @{} "Path $path does not exist !";
- }
-
- # Initialize result information
- $result = @{
- backup = "";
- changed = $false;
- msg = "";
- }
-
- # Read the dest file lines using the indicated encoding into a mutable ArrayList. Note
- # that we have to clean up the path because ansible wants to treat / and \ as
- # interchangeable in windows pathnames, but .NET framework internals do not support that.
- $cleanpath = $path.Replace("/", "\");
- $before = [System.IO.File]::ReadAllLines($cleanpath, $encodingobj);
- If ($null -eq $before) {
- $lines = New-Object System.Collections.ArrayList;
- }
- Else {
- $lines = [System.Collections.ArrayList] $before;
- }
-
- if ($diff_support) {
- $result.diff = @{
- before = $before -join $linesep;
- }
- }
-
- # Compile the regex specified, if provided
- $cre = $null;
- If ($regex) {
- $cre = New-Object Regex $regex, 'Compiled';
- }
-
- $found = New-Object System.Collections.ArrayList;
- $left = New-Object System.Collections.ArrayList;
-
- Foreach ($cur_line in $lines) {
- If ($regex) {
- $m = $cre.Match($cur_line);
- $match_found = $m.Success;
- }
- Else {
- $match_found = $line -ceq $cur_line;
- }
- If ($match_found) {
- $found.Add($cur_line) > $null;
- $result.changed = $true;
- }
- Else {
- $left.Add($cur_line) > $null;
- }
- }
-
- # Write changes to the path if changes were made
- If ($result.changed) {
-
- # Write backup file if backup == "yes"
- If ($backup) {
- $result.backup_file = Backup-File -path $path -WhatIf:$check_mode
- # Ensure backward compatibility (deprecate in future)
- $result.backup = $result.backup_file
- }
-
- $writelines_params = @{
- outlines = $left
- path = $path
- linesep = $linesep
- encodingobj = $encodingobj
- validate = $validate
- check_mode = $check_mode
- }
- $after = WriteLines @writelines_params;
-
- if ($diff_support) {
- $result.diff.after = $after;
- }
- }
-
- $result.encoding = $encodingobj.WebName;
- $result.found = $found.Count;
- $result.msg = "$($found.Count) line(s) removed";
-
- Exit-Json $result;
-}
-
-
-# Parse the parameters file dropped by the Ansible machinery
-$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;
-
-# Initialize defaults for input parameters.
-$path = Get-AnsibleParam -obj $params -name "path" -type "path" -failifempty $true -aliases "dest","destfile","name";
-$regex = Get-AnsibleParam -obj $params -name "regex" -type "str" -aliases "regexp";
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present","absent";
-$line = Get-AnsibleParam -obj $params -name "line" -type "str";
-$backrefs = Get-AnsibleParam -obj $params -name "backrefs" -type "bool" -default $false;
-$insertafter = Get-AnsibleParam -obj $params -name "insertafter" -type "str";
-$insertbefore = Get-AnsibleParam -obj $params -name "insertbefore" -type "str";
-$create = Get-AnsibleParam -obj $params -name "create" -type "bool" -default $false;
-$backup = Get-AnsibleParam -obj $params -name "backup" -type "bool" -default $false;
-$validate = Get-AnsibleParam -obj $params -name "validate" -type "str";
-$encoding = Get-AnsibleParam -obj $params -name "encoding" -type "str" -default "auto";
-$newline = Get-AnsibleParam -obj $params -name "newline" -type "str" -default "windows" -validateset "unix","windows";
-
-# Fail if the path is not a file
-If (Test-Path -LiteralPath $path -PathType "container") {
- Fail-Json @{} "Path $path is a directory";
-}
-
-# Default to windows line separator - probably most common
-$linesep = "`r`n"
-If ($newline -eq "unix") {
- $linesep = "`n";
-}
-
-# Figure out the proper encoding to use for reading / writing the target file.
-
-# The default encoding is UTF-8 without BOM
-$encodingobj = [System.Text.UTF8Encoding] $false;
-
-# If an explicit encoding is specified, use that instead
-If ($encoding -ne "auto") {
- $encodingobj = [System.Text.Encoding]::GetEncoding($encoding);
-}
-
-# Otherwise see if we can determine the current encoding of the target file.
-# If the file doesn't exist yet (create == 'yes') we use the default or
-# explicitly specified encoding set above.
-ElseIf (Test-Path -LiteralPath $path) {
-
- # Get a sorted list of encodings with preambles, longest first
- $max_preamble_len = 0;
- $sortedlist = New-Object System.Collections.SortedList;
- Foreach ($encodinginfo in [System.Text.Encoding]::GetEncodings()) {
- $encoding = $encodinginfo.GetEncoding();
- $plen = $encoding.GetPreamble().Length;
- If ($plen -gt $max_preamble_len) {
- $max_preamble_len = $plen;
- }
- If ($plen -gt 0) {
- $sortedlist.Add(-($plen * 1000000 + $encoding.CodePage), $encoding) > $null;
- }
- }
-
- # Get the first N bytes from the file, where N is the max preamble length we saw
- [Byte[]]$bom = Get-Content -Encoding Byte -ReadCount $max_preamble_len -TotalCount $max_preamble_len -LiteralPath $path;
-
- # Iterate through the sorted encodings, looking for a full match.
- $found = $false;
- Foreach ($encoding in $sortedlist.GetValueList()) {
- $preamble = $encoding.GetPreamble();
- If ($preamble -and $bom) {
- Foreach ($i in 0..($preamble.Length - 1)) {
- If ($i -ge $bom.Length) {
- break;
- }
- If ($preamble[$i] -ne $bom[$i]) {
- break;
- }
- ElseIf ($i + 1 -eq $preamble.Length) {
- $encodingobj = $encoding;
- $found = $true;
- }
- }
- If ($found) {
- break;
- }
- }
- }
-}
-
-
-# Main dispatch - based on the value of 'state', perform argument validation and
-# call the appropriate handler function.
-If ($state -eq "present") {
-
- If ($backrefs -and -not $regex) {
- Fail-Json @{} "regexp= is required with backrefs=true";
- }
-
- If (-not $line) {
- Fail-Json @{} "line= is required with state=present";
- }
-
- If ($insertbefore -and $insertafter) {
- Add-Warning $result "Both insertbefore and insertafter parameters found, ignoring `"insertafter=$insertafter`""
- }
-
- If (-not $insertbefore -and -not $insertafter) {
- $insertafter = "EOF";
- }
-
- $present_params = @{
- path = $path
- regex = $regex
- line = $line
- insertafter = $insertafter
- insertbefore = $insertbefore
- create = $create
- backup = $backup
- backrefs = $backrefs
- validate = $validate
- encodingobj = $encodingobj
- linesep = $linesep
- check_mode = $check_mode
- diff_support = $diff_support
- }
- Present @present_params;
-
-}
-ElseIf ($state -eq "absent") {
-
- If (-not $regex -and -not $line) {
- Fail-Json @{} "one of line= or regexp= is required with state=absent";
- }
-
- $absent_params = @{
- path = $path
- regex = $regex
- line = $line
- backup = $backup
- validate = $validate
- encodingobj = $encodingobj
- linesep = $linesep
- check_mode = $check_mode
- diff_support = $diff_support
- }
- Absent @absent_params;
-}
diff --git a/lib/ansible/modules/windows/win_lineinfile.py b/lib/ansible/modules/windows/win_lineinfile.py
deleted file mode 100644
index f4fb7f5afa..0000000000
--- a/lib/ansible/modules/windows/win_lineinfile.py
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_lineinfile
-short_description: Ensure a particular line is in a file, or replace an existing line using a back-referenced regular expression
-description:
- - This module will search a file for a line, and ensure that it is present or absent.
- - This is primarily useful when you want to change a single line in a file only.
-version_added: "2.0"
-options:
- path:
- description:
- - The path of the file to modify.
- - Note that the Windows path delimiter C(\) must be escaped as C(\\) when the line is double quoted.
- - Before Ansible 2.3 this option was only usable as I(dest), I(destfile) and I(name).
- type: path
- required: yes
- aliases: [ dest, destfile, name ]
- backup:
- description:
- - Determine whether a backup should be created.
- - When set to C(yes), create a backup file including the timestamp information
- so you can get the original file back if you somehow clobbered it incorrectly.
- type: bool
- default: no
- regex:
- description:
- - The regular expression to look for in every line of the file. For C(state=present), the pattern to replace if found; only the last line found
- will be replaced. For C(state=absent), the pattern of the line to remove. Uses .NET compatible regular expressions;
- see U(https://msdn.microsoft.com/en-us/library/hs600312%28v=vs.110%29.aspx).
- aliases: [ "regexp" ]
- state:
- description:
- - Whether the line should be there or not.
- type: str
- choices: [ absent, present ]
- default: present
- line:
- description:
- - Required for C(state=present). The line to insert/replace into the file. If C(backrefs) is set, may contain backreferences that will get
- expanded with the C(regexp) capture groups if the regexp matches.
- - Be aware that the line is processed first on the controller and thus is dependent on yaml quoting rules. Any double quoted line
- will have control characters, such as '\r\n', expanded. To print such characters literally, use single or no quotes.
- type: str
- backrefs:
- description:
- - Used with C(state=present). If set, line can contain backreferences (both positional and named) that will get populated if the C(regexp)
- matches. This flag changes the operation of the module slightly; C(insertbefore) and C(insertafter) will be ignored, and if the C(regexp)
- doesn't match anywhere in the file, the file will be left unchanged.
- - If the C(regexp) does match, the last matching line will be replaced by the expanded line parameter.
- type: bool
- default: no
- insertafter:
- description:
- - Used with C(state=present). If specified, the line will be inserted after the last match of specified regular expression. A special value is
- available; C(EOF) for inserting the line at the end of the file.
- - If specified regular expression has no matches, EOF will be used instead. May not be used with C(backrefs).
- type: str
- choices: [ EOF, '*regex*' ]
- default: EOF
- insertbefore:
- description:
- - Used with C(state=present). If specified, the line will be inserted before the last match of specified regular expression. A value is available;
- C(BOF) for inserting the line at the beginning of the file.
- - If specified regular expression has no matches, the line will be inserted at the end of the file. May not be used with C(backrefs).
- type: str
- choices: [ BOF, '*regex*' ]
- create:
- description:
- - Used with C(state=present). If specified, the file will be created if it does not already exist. By default it will fail if the file is missing.
- type: bool
- default: no
- validate:
- description:
- - Validation to run before copying into place. Use %s in the command to indicate the current file to validate.
- - The command is passed securely so shell features like expansion and pipes won't work.
- type: str
- encoding:
- description:
- - Specifies the encoding of the source text file to operate on (and thus what the output encoding will be). The default of C(auto) will cause
- the module to auto-detect the encoding of the source file and ensure that the modified file is written with the same encoding.
- - An explicit encoding can be passed as a string that is a valid value to pass to the .NET framework System.Text.Encoding.GetEncoding() method -
- see U(https://msdn.microsoft.com/en-us/library/system.text.encoding%28v=vs.110%29.aspx).
- - This is mostly useful with C(create=yes) if you want to create a new file with a specific encoding. If C(create=yes) is specified without a
- specific encoding, the default encoding (UTF-8, no BOM) will be used.
- type: str
- default: auto
- newline:
- description:
- - Specifies the line separator style to use for the modified file. This defaults to the windows line separator (C(\r\n)). Note that the indicated
- line separator will be used for file output regardless of the original line separator that appears in the input file.
- type: str
- choices: [ unix, windows ]
- default: windows
-notes:
- - As of Ansible 2.3, the I(dest) option has been changed to I(path) as default, but I(dest) still works as well.
-seealso:
-- module: assemble
-- module: lineinfile
-author:
-- Brian Lloyd (@brianlloyd)
-'''
-
-EXAMPLES = r'''
-# Before Ansible 2.3, option 'dest', 'destfile' or 'name' was used instead of 'path'
-- name: Insert path without converting \r\n
- win_lineinfile:
- path: c:\file.txt
- line: c:\return\new
-
-- win_lineinfile:
- path: C:\Temp\example.conf
- regex: '^name='
- line: 'name=JohnDoe'
-
-- win_lineinfile:
- path: C:\Temp\example.conf
- regex: '^name='
- state: absent
-
-- win_lineinfile:
- path: C:\Temp\example.conf
- regex: '^127\.0\.0\.1'
- line: '127.0.0.1 localhost'
-
-- win_lineinfile:
- path: C:\Temp\httpd.conf
- regex: '^Listen '
- insertafter: '^#Listen '
- line: Listen 8080
-
-- win_lineinfile:
- path: C:\Temp\services
- regex: '^# port for http'
- insertbefore: '^www.*80/tcp'
- line: '# port for http by default'
-
-- name: Create file if it doesn't exist with a specific encoding
- win_lineinfile:
- path: C:\Temp\utf16.txt
- create: yes
- encoding: utf-16
- line: This is a utf-16 encoded file
-
-- name: Add a line to a file and ensure the resulting file uses unix line separators
- win_lineinfile:
- path: C:\Temp\testfile.txt
- line: Line added to file
- newline: unix
-
-- name: Update a line using backrefs
- win_lineinfile:
- path: C:\Temp\example.conf
- backrefs: yes
- regex: '(^name=)'
- line: '$1JohnDoe'
-'''
-
-RETURN = r'''
-backup:
- description:
- - Name of the backup file that was created.
- - This is now deprecated, use C(backup_file) instead.
- returned: if backup=yes
- type: str
- sample: C:\Path\To\File.txt.11540.20150212-220915.bak
-backup_file:
- description: Name of the backup file that was created.
- returned: if backup=yes
- type: str
- sample: C:\Path\To\File.txt.11540.20150212-220915.bak
-'''
diff --git a/lib/ansible/modules/windows/win_mapped_drive.ps1 b/lib/ansible/modules/windows/win_mapped_drive.ps1
deleted file mode 100644
index aab65d455c..0000000000
--- a/lib/ansible/modules/windows/win_mapped_drive.ps1
+++ /dev/null
@@ -1,444 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.AccessToken
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.AddType
-
-$spec = @{
- options = @{
- letter = @{ type = "str"; required = $true }
- path = @{ type = "path"; }
- state = @{ type = "str"; default = "present"; choices = @("absent", "present") }
- username = @{ type = "str" }
- password = @{ type = "str"; no_log = $true }
- }
- required_if = @(
- ,@("state", "present", @("path"))
- )
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$letter = $module.Params.letter
-$path = $module.Params.path
-$state = $module.Params.state
-$username = $module.Params.username
-$password = $module.Params.password
-
-if ($letter -notmatch "^[a-zA-z]{1}$") {
- $module.FailJson("letter must be a single letter from A-Z, was: $letter")
-}
-$letter_root = "$($letter):"
-
-$module.Diff.before = ""
-$module.Diff.after = ""
-
-Add-CSharpType -AnsibleModule $module -References @'
-using Microsoft.Win32.SafeHandles;
-using System;
-using System.Collections.Generic;
-using System.Runtime.ConstrainedExecution;
-using System.Runtime.InteropServices;
-
-namespace Ansible.MappedDrive
-{
- internal class NativeHelpers
- {
- public enum ResourceScope : uint
- {
- Connected = 0x00000001,
- GlobalNet = 0x00000002,
- Remembered = 0x00000003,
- Recent = 0x00000004,
- Context = 0x00000005,
- }
-
- [Flags]
- public enum ResourceType : uint
- {
- Any = 0x0000000,
- Disk = 0x00000001,
- Print = 0x00000002,
- Reserved = 0x00000008,
- Unknown = 0xFFFFFFFF,
- }
-
- public enum CloseFlags : uint
- {
- None = 0x00000000,
- UpdateProfile = 0x00000001,
- }
-
- [Flags]
- public enum AddFlags : uint
- {
- UpdateProfile = 0x00000001,
- UpdateRecent = 0x00000002,
- Temporary = 0x00000004,
- Interactive = 0x00000008,
- Prompt = 0x00000010,
- Redirect = 0x00000080,
- CurrentMedia = 0x00000200,
- CommandLine = 0x00000800,
- CmdSaveCred = 0x00001000,
- CredReset = 0x00002000,
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct NETRESOURCEW
- {
- public ResourceScope dwScope;
- public ResourceType dwType;
- public UInt32 dwDisplayType;
- public UInt32 dwUsage;
- [MarshalAs(UnmanagedType.LPWStr)] public string lpLocalName;
- [MarshalAs(UnmanagedType.LPWStr)] public string lpRemoteName;
- [MarshalAs(UnmanagedType.LPWStr)] public string lpComment;
- [MarshalAs(UnmanagedType.LPWStr)] public string lpProvider;
- }
- }
-
- internal class NativeMethods
- {
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool CloseHandle(
- IntPtr hObject);
-
- [DllImport("advapi32.dll", SetLastError = true)]
- public static extern bool ImpersonateLoggedOnUser(
- IntPtr hToken);
-
- [DllImport("advapi32.dll", SetLastError = true)]
- public static extern bool RevertToSelf();
-
- [DllImport("Mpr.dll", CharSet = CharSet.Unicode)]
- public static extern UInt32 WNetAddConnection2W(
- NativeHelpers.NETRESOURCEW lpNetResource,
- [MarshalAs(UnmanagedType.LPWStr)] string lpPassword,
- [MarshalAs(UnmanagedType.LPWStr)] string lpUserName,
- NativeHelpers.AddFlags dwFlags);
-
- [DllImport("Mpr.dll", CharSet = CharSet.Unicode)]
- public static extern UInt32 WNetCancelConnection2W(
- [MarshalAs(UnmanagedType.LPWStr)] string lpName,
- NativeHelpers.CloseFlags dwFlags,
- bool fForce);
-
- [DllImport("Mpr.dll")]
- public static extern UInt32 WNetCloseEnum(
- IntPtr hEnum);
-
- [DllImport("Mpr.dll", CharSet = CharSet.Unicode)]
- public static extern UInt32 WNetEnumResourceW(
- IntPtr hEnum,
- ref Int32 lpcCount,
- SafeMemoryBuffer lpBuffer,
- ref UInt32 lpBufferSize);
-
- [DllImport("Mpr.dll", CharSet = CharSet.Unicode)]
- public static extern UInt32 WNetOpenEnumW(
- NativeHelpers.ResourceScope dwScope,
- NativeHelpers.ResourceType dwType,
- UInt32 dwUsage,
- IntPtr lpNetResource,
- out IntPtr lphEnum);
- }
-
- internal class SafeMemoryBuffer : SafeHandleZeroOrMinusOneIsInvalid
- {
- public SafeMemoryBuffer() : base(true) { }
- public SafeMemoryBuffer(int cb) : base(true)
- {
- base.SetHandle(Marshal.AllocHGlobal(cb));
- }
- public SafeMemoryBuffer(IntPtr handle) : base(true)
- {
- base.SetHandle(handle);
- }
-
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
- protected override bool ReleaseHandle()
- {
- Marshal.FreeHGlobal(handle);
- return true;
- }
- }
-
- internal class Impersonation : IDisposable
- {
- private IntPtr hToken = IntPtr.Zero;
-
- public Impersonation(IntPtr token)
- {
- hToken = token;
- if (token != IntPtr.Zero)
- if (!NativeMethods.ImpersonateLoggedOnUser(hToken))
- throw new Win32Exception("Failed to impersonate token with ImpersonateLoggedOnUser()");
- }
-
- public void Dispose()
- {
- if (hToken != null)
- NativeMethods.RevertToSelf();
- GC.SuppressFinalize(this);
- }
- ~Impersonation() { Dispose(); }
- }
-
- public class DriveInfo
- {
- public string Drive;
- public string Path;
- }
-
- public class Win32Exception : System.ComponentModel.Win32Exception
- {
- private string _msg;
- public Win32Exception(string message) : this(Marshal.GetLastWin32Error(), message) { }
- public Win32Exception(int errorCode, string message) : base(errorCode)
- {
- _msg = String.Format("{0} ({1}, Win32ErrorCode {2})", message, base.Message, errorCode);
- }
- public override string Message { get { return _msg; } }
- public static explicit operator Win32Exception(string message) { return new Win32Exception(message); }
- }
-
- public class Utils
- {
- private const UInt32 ERROR_SUCCESS = 0x00000000;
- private const UInt32 ERROR_NO_MORE_ITEMS = 0x0000103;
-
- public static void AddMappedDrive(string drive, string path, IntPtr iToken, string username = null, string password = null)
- {
- NativeHelpers.NETRESOURCEW resource = new NativeHelpers.NETRESOURCEW
- {
- dwType = NativeHelpers.ResourceType.Disk,
- lpLocalName = drive,
- lpRemoteName = path,
- };
- NativeHelpers.AddFlags dwFlags = NativeHelpers.AddFlags.UpdateProfile;
- // While WNetAddConnection2W supports user/pass, this is only used for the first connection and the
- // password is not remembered. We will delete the username mapping afterwards as it interferes with
- // the implicit credential cache used in Windows
- using (Impersonation imp = new Impersonation(iToken))
- {
- UInt32 res = NativeMethods.WNetAddConnection2W(resource, password, username, dwFlags);
- if (res != ERROR_SUCCESS)
- throw new Win32Exception((int)res, String.Format("Failed to map {0} to '{1}' with WNetAddConnection2W()", drive, path));
- }
- }
-
- public static List<DriveInfo> GetMappedDrives(IntPtr iToken)
- {
- using (Impersonation imp = new Impersonation(iToken))
- {
- IntPtr enumPtr = IntPtr.Zero;
- UInt32 res = NativeMethods.WNetOpenEnumW(NativeHelpers.ResourceScope.Remembered, NativeHelpers.ResourceType.Disk,
- 0, IntPtr.Zero, out enumPtr);
- if (res != ERROR_SUCCESS)
- throw new Win32Exception((int)res, "WNetOpenEnumW()");
-
- List<DriveInfo> resources = new List<DriveInfo>();
- try
- {
- // MS recommend a buffer size of 16 KiB
- UInt32 bufferSize = 16384;
- int lpcCount = -1;
-
- // keep iterating the enum until ERROR_NO_MORE_ITEMS is returned
- do
- {
- using (SafeMemoryBuffer buffer = new SafeMemoryBuffer((int)bufferSize))
- {
- res = NativeMethods.WNetEnumResourceW(enumPtr, ref lpcCount, buffer, ref bufferSize);
- if (res == ERROR_NO_MORE_ITEMS)
- continue;
- else if (res != ERROR_SUCCESS)
- throw new Win32Exception((int)res, "WNetEnumResourceW()");
- lpcCount = lpcCount < 0 ? 0 : lpcCount;
-
- NativeHelpers.NETRESOURCEW[] rawResources = new NativeHelpers.NETRESOURCEW[lpcCount];
- PtrToStructureArray(rawResources, buffer.DangerousGetHandle());
- foreach (NativeHelpers.NETRESOURCEW resource in rawResources)
- {
- DriveInfo currentDrive = new DriveInfo
- {
- Drive = resource.lpLocalName,
- Path = resource.lpRemoteName,
- };
- resources.Add(currentDrive);
- }
- }
- }
- while (res != ERROR_NO_MORE_ITEMS);
- }
- finally
- {
- NativeMethods.WNetCloseEnum(enumPtr);
- }
-
- return resources;
- }
- }
-
- public static void RemoveMappedDrive(string drive, IntPtr iToken)
- {
- using (Impersonation imp = new Impersonation(iToken))
- {
- UInt32 res = NativeMethods.WNetCancelConnection2W(drive, NativeHelpers.CloseFlags.UpdateProfile, true);
- if (res != ERROR_SUCCESS)
- throw new Win32Exception((int)res, String.Format("Failed to remove mapped drive {0} with WNetCancelConnection2W()", drive));
- }
- }
-
- private static void PtrToStructureArray<T>(T[] array, IntPtr ptr)
- {
- IntPtr ptrOffset = ptr;
- for (int i = 0; i < array.Length; i++, ptrOffset = IntPtr.Add(ptrOffset, Marshal.SizeOf(typeof(T))))
- array[i] = (T)Marshal.PtrToStructure(ptrOffset, typeof(T));
- }
- }
-}
-'@
-
-Function Get-LimitedToken {
- $h_process = [Ansible.AccessToken.TokenUtil]::OpenProcess()
- $h_token = [Ansible.AccessToken.TokenUtil]::OpenProcessToken($h_process, "Duplicate, Query")
-
- try {
- # If we don't have a Full token, we don't need to get the limited one to set a mapped drive
- $tet = [Ansible.AccessToken.TokenUtil]::GetTokenElevationType($h_token)
- if ($tet -ne [Ansible.AccessToken.TokenElevationType]::Full) {
- return
- }
-
- foreach ($system_token in [Ansible.AccessToken.TokenUtil]::EnumerateUserTokens("S-1-5-18", "Duplicate")) {
- # To get the TokenLinkedToken we need the SeTcbPrivilege, not all SYSTEM tokens have this assigned so
- # we need to check before impersonating that token
- $token_privileges = [Ansible.AccessToken.TokenUtil]::GetTokenPrivileges($system_token)
- if ($null -eq ($token_privileges | Where-Object { $_.Name -eq "SeTcbPrivilege" })) {
- continue
- }
-
- [Ansible.AccessToken.TokenUtil]::ImpersonateToken($system_token)
- try {
- return [Ansible.AccessToken.TokenUtil]::GetTokenLinkedToken($h_token)
- } finally {
- [Ansible.AccessToken.TokenUtil]::RevertToSelf()
- }
- }
- } finally {
- $h_token.Dispose()
- }
-}
-
-<#
-When we run with become and UAC is enabled, the become process will most likely be the Admin/Full token. This is
-an issue with the WNetConnection APIs as the Full token is unable to add/enumerate/remove connections due to
-Windows storing the connection details on each token session ID. Unless EnabledLinkedConnections (reg key) is
-set to 1, the Full token is unable to manage connections in a persisted way whereas the Limited token is. This
-is similar to running 'net use' normally and an admin process is unable to see those and vice versa.
-
-To overcome this problem, we attempt to get a handle on the Limited token for the current logon and impersonate
-that before making any WNetConnection calls. If the token is not split, or we are already running on the Limited
-token then no impersonatoin is used/required. This allows the module to run with become (required to access the
-credential store) but still be able to manage the mapped connections.
-
-These are the following scenarios we have to handle;
-
- 1. Run without become
- A network logon is usually not split so GetLimitedToken() will return $null and no impersonation is needed
- 2. Run with become on admin user with admin priv
- We will have a Full token, GetLimitedToken() will return the limited token and impersonation is used
- 3. Run with become on admin user without admin priv
- We are already running with a Limited token, GetLimitedToken() return $nul and no impersonation is needed
- 4. Run with become on standard user
- There's no split token, GetLimitedToken() will return $null and no impersonation is needed
-#>
-$impersonation_token = Get-LimitedToken
-
-try {
- $i_token_ptr = [System.IntPtr]::Zero
- if ($null -ne $impersonation_token) {
- $i_token_ptr = $impersonation_token.DangerousGetHandle()
- }
-
- $existing_targets = [Ansible.MappedDrive.Utils]::GetMappedDrives($i_token_ptr)
- $existing_target = $existing_targets | Where-Object { $_.Drive -eq $letter_root }
-
- if ($existing_target) {
- $module.Diff.before = @{
- letter = $letter
- path = $existing_target.Path
- }
- }
-
- if ($state -eq "absent") {
- if ($null -ne $existing_target) {
- if ($null -ne $path -and $existing_target.Path -ne $path) {
- $module.FailJson("did not delete mapped drive $letter, the target path is pointing to a different location at $( $existing_target.Path )")
- }
- if (-not $module.CheckMode) {
- [Ansible.MappedDrive.Utils]::RemoveMappedDrive($letter_root, $i_token_ptr)
- }
-
- $module.Result.changed = $true
- }
- } else {
- $physical_drives = Get-PSDrive -PSProvider "FileSystem"
- if ($letter -in $physical_drives.Name) {
- $module.FailJson("failed to create mapped drive $letter, this letter is in use and is pointing to a non UNC path")
- }
-
- # PowerShell converts a $null value to "" when crossing the .NET marshaler, we need to convert the input
- # to a missing value so it uses the defaults. We also need to Invoke it with MethodInfo.Invoke so the defaults
- # are still used
- $input_username = $username
- if ($null -eq $username) {
- $input_username = [Type]::Missing
- }
- $input_password = $password
- if ($null -eq $password) {
- $input_password = [Type]::Missing
- }
- $add_method = [Ansible.MappedDrive.Utils].GetMethod("AddMappedDrive")
-
- if ($null -ne $existing_target) {
- if ($existing_target.Path -ne $path) {
- if (-not $module.CheckMode) {
- [Ansible.MappedDrive.Utils]::RemoveMappedDrive($letter_root, $i_token_ptr)
- $add_method.Invoke($null, [Object[]]@($letter_root, $path, $i_token_ptr, $input_username, $input_password))
- }
- $module.Result.changed = $true
- }
- } else {
- if (-not $module.CheckMode) {
- $add_method.Invoke($null, [Object[]]@($letter_root, $path, $i_token_ptr, $input_username, $input_password))
- }
-
- $module.Result.changed = $true
- }
-
- # If username was set and we made a change, remove the UserName value so Windows will continue to use the cred
- # cache. If we don't do this then the drive will fail to map in the future as WNetAddConnection does not cache
- # the password and relies on the credential store.
- if ($null -ne $username -and $module.Result.changed -and -not $module.CheckMode) {
- Set-ItemProperty -Path HKCU:\Network\$letter -Name UserName -Value "" -WhatIf:$module.CheckMode
- }
-
- $module.Diff.after = @{
- letter = $letter
- path = $path
- }
- }
-} finally {
- if ($null -ne $impersonation_token) {
- $impersonation_token.Dispose()
- }
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_mapped_drive.py b/lib/ansible/modules/windows/win_mapped_drive.py
deleted file mode 100644
index 3b2a0f6372..0000000000
--- a/lib/ansible/modules/windows/win_mapped_drive.py
+++ /dev/null
@@ -1,155 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub, actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_mapped_drive
-version_added: '2.4'
-short_description: Map network drives for users
-description:
-- Allows you to modify mapped network drives for individual users.
-- Also support WebDAV endpoints in the UNC form.
-options:
- letter:
- description:
- - The letter of the network path to map to.
- - This letter must not already be in use with Windows.
- type: str
- required: yes
- password:
- description:
- - The password for C(username) that is used when testing the initial
- connection.
- - This is never saved with a mapped drive, use the M(win_credential) module
- to persist a username and password for a host.
- type: str
- path:
- description:
- - The UNC path to map the drive to.
- - If pointing to a WebDAV location this must still be in a UNC path in the
- format C(\\hostname\path) and not a URL, see examples for more details.
- - To specify a C(https) WebDAV path, add C(@SSL) after the hostname. To
- specify a custom WebDAV port add C(@<port num>) after the C(@SSL) or
- hostname portion of the UNC path, e.g. C(\\server@SSL@1234) or
- C(\\server@1234).
- - This is required if C(state=present).
- - If C(state=absent) and I(path) is not set, the module will delete the
- mapped drive regardless of the target.
- - If C(state=absent) and the I(path) is set, the module will throw an error
- if path does not match the target of the mapped drive.
- type: path
- state:
- description:
- - If C(present) will ensure the mapped drive exists.
- - If C(absent) will ensure the mapped drive does not exist.
- type: str
- choices: [ absent, present ]
- default: present
- username:
- description:
- - The username that is used when testing the initial connection.
- - This is never saved with a mapped drive, the M(win_credential) module
- to persist a username and password for a host.
- - This is required if the mapped drive requires authentication with
- custom credentials and become, or CredSSP cannot be used.
- - If become or CredSSP is used, any credentials saved with
- M(win_credential) will automatically be used instead.
- type: str
-notes:
-- You cannot use this module to access a mapped drive in another Ansible task,
- drives mapped with this module are only accessible when logging in
- interactively with the user through the console or RDP.
-- It is recommend to run this module with become or CredSSP when the remote
- path requires authentication.
-- When using become or CredSSP, the task will have access to any local
- credentials stored in the user's vault.
-- If become or CredSSP is not available, the I(username) and I(password)
- options can be used for the initial authentication but these are not
- persisted.
-- WebDAV paths must have the WebDAV client feature installed for this module to
- map those paths. This is installed by default on desktop Windows editions but
- Windows Server hosts need to install the C(WebDAV-Redirector) feature using
- M(win_feature).
-seealso:
-- module: win_credential
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Create a mapped drive under Z
- win_mapped_drive:
- letter: Z
- path: \\domain\appdata\accounting
-
-- name: Delete any mapped drives under Z
- win_mapped_drive:
- letter: Z
- state: absent
-
-- name: Only delete the mapped drive Z if the paths match (error is thrown otherwise)
- win_mapped_drive:
- letter: Z
- path: \\domain\appdata\accounting
- state: absent
-
-- name: Create mapped drive with credentials and save the username and password
- block:
- - name: Save the network credentials required for the mapped drive
- win_credential:
- name: server
- type: domain_password
- username: username@DOMAIN
- secret: Password01
- state: present
-
- - name: Create a mapped drive that requires authentication
- win_mapped_drive:
- letter: M
- path: \\SERVER\C$
- state: present
- vars:
- # become is required to save and retrieve the credentials in the tasks
- ansible_become: yes
- ansible_become_method: runas
- ansible_become_user: '{{ ansible_user }}'
- ansible_become_pass: '{{ ansible_password }}'
-
-- name: Create mapped drive with credentials that do not persist on the next logon
- win_mapped_drive:
- letter: M
- path: \\SERVER\C$
- state: present
- username: '{{ ansible_user }}'
- password: '{{ ansible_password }}'
-
-# This should only be required for Windows Server OS'
-- name: Ensure WebDAV client feature is installed
- win_feature:
- name: WebDAV-Redirector
- state: present
- register: webdav_feature
-
-- name: Reboot after installing WebDAV client feature
- win_reboot:
- when: webdav_feature.reboot_required
-
-- name: Map the HTTPS WebDAV location
- win_mapped_drive:
- letter: W
- path: \\live.sysinternals.com@SSL\tools # https://live.sysinternals.com/tools
- state: present
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_msg.ps1 b/lib/ansible/modules/windows/win_msg.ps1
deleted file mode 100644
index 63fe680024..0000000000
--- a/lib/ansible/modules/windows/win_msg.ps1
+++ /dev/null
@@ -1,52 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2016, Jon Hawkesworth (@jhawkesworth) <figs@unity.demon.co.uk>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#
-$stopwatch = [system.diagnostics.stopwatch]::startNew()
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$display_seconds = Get-AnsibleParam -obj $params -name "display_seconds" -type "int" -default "10"
-$msg = Get-AnsibleParam -obj $params -name "msg" -type "str" -default "Hello world!"
-$to = Get-AnsibleParam -obj $params -name "to" -type "str" -default "*"
-$wait = Get-AnsibleParam -obj $params -name "wait" -type "bool" -default $false
-
-$result = @{
- changed = $false
- display_seconds = $display_seconds
- msg = $msg
- wait = $wait
-}
-
-if ($msg.Length -gt 255) {
- Fail-Json -obj $result -message "msg length must be less than 256 characters, current length: $($msg.Length)"
-}
-
-$msg_args = @($to, "/TIME:$display_seconds")
-
-if ($wait) {
- $msg_args += "/W"
-}
-
-$msg_args += $msg
-if (-not $check_mode) {
- $output = & msg.exe $msg_args 2>&1
- $result.rc = $LASTEXITCODE
-}
-
-$endsend_at = Get-Date| Out-String
-$stopwatch.Stop()
-
-$result.changed = $true
-$result.runtime_seconds = $stopwatch.Elapsed.TotalSeconds
-$result.sent_localtime = $endsend_at.Trim()
-
-if ($result.rc -ne 0 ) {
- Fail-Json -obj $result -message "$output"
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_msg.py b/lib/ansible/modules/windows/win_msg.py
deleted file mode 100644
index 4f9ea959de..0000000000
--- a/lib/ansible/modules/windows/win_msg.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Jon Hawkesworth (@jhawkesworth) <figs@unity.demon.co.uk>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_msg
-version_added: "2.3"
-short_description: Sends a message to logged in users on Windows hosts
-description:
- - Wraps the msg.exe command in order to send messages to Windows hosts.
-options:
- to:
- description:
- - Who to send the message to. Can be a username, sessionname or sessionid.
- type: str
- default: '*'
- display_seconds:
- description:
- - How long to wait for receiver to acknowledge message, in seconds.
- type: int
- default: 10
- wait:
- description:
- - Whether to wait for users to respond. Module will only wait for the number of seconds specified in display_seconds or 10 seconds if not specified.
- However, if I(wait) is C(yes), the message is sent to each logged on user in turn, waiting for the user to either press 'ok' or for
- the timeout to elapse before moving on to the next user.
- type: bool
- default: 'no'
- msg:
- description:
- - The text of the message to be displayed.
- - The message must be less than 256 characters.
- type: str
- default: Hello world!
-notes:
- - This module must run on a windows host, so ensure your play targets windows
- hosts, or delegates to a windows host.
- - Messages are only sent to the local host where the module is run.
- - The module does not support sending to users listed in a file.
- - Setting wait to C(yes) can result in long run times on systems with many logged in users.
-seealso:
-- module: win_say
-- module: win_toast
-author:
-- Jon Hawkesworth (@jhawkesworth)
-'''
-
-EXAMPLES = r'''
-- name: Warn logged in users of impending upgrade
- win_msg:
- display_seconds: 60
- msg: Automated upgrade about to start. Please save your work and log off before {{ deployment_start_time }}
-'''
-
-RETURN = r'''
-msg:
- description: Test of the message that was sent.
- returned: changed
- type: str
- sample: Automated upgrade about to start. Please save your work and log off before 22 July 2016 18:00:00
-display_seconds:
- description: Value of display_seconds module parameter.
- returned: success
- type: str
- sample: 10
-rc:
- description: The return code of the API call.
- returned: always
- type: int
- sample: 0
-runtime_seconds:
- description: How long the module took to run on the remote windows host.
- returned: success
- type: str
- sample: 22 July 2016 17:45:51
-sent_localtime:
- description: local time from windows host when the message was sent.
- returned: success
- type: str
- sample: 22 July 2016 17:45:51
-wait:
- description: Value of wait module parameter.
- returned: success
- type: bool
- sample: false
-'''
diff --git a/lib/ansible/modules/windows/win_netbios.ps1 b/lib/ansible/modules/windows/win_netbios.ps1
deleted file mode 100644
index 0179a40260..0000000000
--- a/lib/ansible/modules/windows/win_netbios.ps1
+++ /dev/null
@@ -1,72 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Thomas Moore (@tmmruk) <hi@tmmr.uk>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-$spec = @{
- options = @{
- state = @{ type = "str"; choices = "enabled", "disabled", "default"; required = $true }
- adapter_names = @{ type = "list"; required = $false }
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-$module.Result.reboot_required = $false
-
-$state = $module.Params.state
-$adapter_names = $module.Params.adapter_names
-
-switch ( $state )
-{
- 'default'{ $netbiosoption = 0 }
- enabled { $netbiosoption = 1 }
- disabled { $netbiosoption = 2 }
-}
-
-if(-not $adapter_names)
-{
- # Target all network adapters on the system
- $get_params = @{
- ClassName = 'Win32_NetworkAdapterConfiguration'
- Filter = 'IPEnabled=true'
- Property = @('MacAddress', 'TcpipNetbiosOptions')
- }
- $target_adapters_config = Get-CimInstance @get_params
-}
-else
-{
- $get_params = @{
- Class = 'Win32_NetworkAdapter'
- Filter = ($adapter_names | ForEach-Object -Process { "NetConnectionId='$_'" }) -join " OR "
- KeyOnly = $true
- }
- $target_adapters_config = Get-CimInstance @get_params | Get-CimAssociatedInstance -ResultClass 'Win32_NetworkAdapterConfiguration'
- if(($target_adapters_config | Measure-Object).Count -ne $adapter_names.Count)
- {
- $module.FailJson("Not all of the target adapter names could be found on the system. No configuration changes have been made. $adapter_names")
- }
-}
-
-foreach($adapter in $target_adapters_config)
-{
- if($adapter.TcpipNetbiosOptions -ne $netbiosoption)
- {
- if(-not $module.CheckMode)
- {
- $result = Invoke-CimMethod -InputObject $adapter -MethodName SetTcpipNetbios -Arguments @{TcpipNetbiosOptions=$netbiosoption}
- switch ( $result.ReturnValue )
- {
- 0 { <# Success no reboot required #> }
- 1 { $module.Result.reboot_required = $true }
- 100 { $module.Warn("DHCP not enabled on adapter $($adapter.MacAddress). Unable to set default. Try using disabled or enabled options instead.") }
- default { $module.FailJson("An error occurred while setting TcpipNetbios options on adapter $($adapter.MacAddress). Return code $($result.ReturnValue).") }
- }
- }
- $module.Result.changed = $true
- }
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_netbios.py b/lib/ansible/modules/windows/win_netbios.py
deleted file mode 100644
index a3bd0dfac0..0000000000
--- a/lib/ansible/modules/windows/win_netbios.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2019, Thomas Moore (@tmmruk)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_netbios
-version_added: '2.9'
-short_description: Manage NetBIOS over TCP/IP settings on Windows.
-description:
- - Enables or disables NetBIOS on Windows network adapters.
- - Can be used to protect a system against NBT-NS poisoning and avoid NBNS broadcast storms.
- - Settings can be applied system wide or per adapter.
-options:
- state:
- description:
- - Whether NetBIOS should be enabled, disabled, or default (use setting from DHCP server or if static IP address is assigned enable NetBIOS).
- choices:
- - enabled
- - disabled
- - default
- required: yes
- type: str
- adapter_names:
- description:
- - List of adapter names for which to manage NetBIOS settings. If this option is omitted then configuration is applied to all adapters on the system.
- - The adapter name used is the connection caption in the Network Control Panel or via C(Get-NetAdapter), eg C(Ethernet 2).
- type: list
- required: no
-
-author:
- - Thomas Moore (@tmmruk)
-notes:
- - Changing NetBIOS settings does not usually require a reboot and will take effect immediately.
- - UDP port 137/138/139 will no longer be listening once NetBIOS is disabled.
-'''
-
-EXAMPLES = r'''
-- name: Disable NetBIOS system wide
- win_netbios:
- state: disabled
-
-- name: Disable NetBIOS on Ethernet2
- win_netbios:
- state: disabled
- adapter_names:
- - Ethernet2
-
-- name: Enable NetBIOS on Public and Backup adapters
- win_netbios:
- state: enabled
- adapter_names:
- - Public
- - Backup
-
-- name: Set NetBIOS to system default on all adapters
- win_netbios:
- state: default
-
-'''
-
-RETURN = r'''
-reboot_required:
- description: Boolean value stating whether a system reboot is required.
- returned: always
- type: bool
- sample: true
-'''
diff --git a/lib/ansible/modules/windows/win_nssm.ps1 b/lib/ansible/modules/windows/win_nssm.ps1
deleted file mode 100644
index e351beebf5..0000000000
--- a/lib/ansible/modules/windows/win_nssm.ps1
+++ /dev/null
@@ -1,498 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, George Frank <george@georgefrank.net>
-# Copyright: (c) 2015, Adam Keech <akeech@chathamfinancial.com>
-# Copyright: (c) 2015, Hans-Joachim Kliemeck <git@kliemeck.de>
-# Copyright: (c) 2019, Kevin Subileau (@ksubileau)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.ArgvParser
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-
-$ErrorActionPreference = "Stop"
-
-$start_modes_map = @{
- "auto" = "SERVICE_AUTO_START"
- "delayed" = "SERVICE_DELAYED_AUTO_START"
- "manual" = "SERVICE_DEMAND_START"
- "disabled" = "SERVICE_DISABLED"
-}
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -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","absent","started","stopped","restarted" -resultobj $result
-$display_name = Get-AnsibleParam -obj $params -name 'display_name' -type 'str'
-$description = Get-AnsibleParam -obj $params -name 'description' -type 'str'
-
-$application = Get-AnsibleParam -obj $params -name "application" -type "path"
-$appDirectory = Get-AnsibleParam -obj $params -name "working_directory" -aliases "app_directory","chdir" -type "path"
-$appParameters = Get-AnsibleParam -obj $params -name "app_parameters"
-$appArguments = Get-AnsibleParam -obj $params -name "arguments" -aliases "app_parameters_free_form"
-
-$stdoutFile = Get-AnsibleParam -obj $params -name "stdout_file" -type "path"
-$stderrFile = Get-AnsibleParam -obj $params -name "stderr_file" -type "path"
-
-$executable = Get-AnsibleParam -obj $params -name "executable" -type "path" -default "nssm.exe"
-
-$app_rotate_bytes = Get-AnsibleParam -obj $params -name "app_rotate_bytes" -type "int" -default 104858
-$app_rotate_online = Get-AnsibleParam -obj $params -name "app_rotate_online" -type "int" -default 0 -validateset 0,1
-$app_stop_method_console = Get-AnsibleParam -obj $params -name "app_stop_method_console" -type "int"
-$app_stop_method_skip = Get-AnsibleParam -obj $params -name "app_stop_method_skip" -type "int" -validateset 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-
-# Deprecated options since 2.8. Remove in 2.12
-$startMode = Get-AnsibleParam -obj $params -name "start_mode" -type "str" -default "auto" -validateset $start_modes_map.Keys -resultobj $result
-$dependencies = Get-AnsibleParam -obj $params -name "dependencies" -type "list"
-$user = Get-AnsibleParam -obj $params -name "user" -type "str"
-$password = Get-AnsibleParam -obj $params -name "password" -type "str"
-
-$result = @{
- changed = $false
-}
-$diff_text = $null
-
-function Invoke-NssmCommand {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true,ValueFromRemainingArguments=$true)]
- [string[]]$arguments
- )
-
- $command = Argv-ToString -arguments (@($executable) + $arguments)
- $result = Run-Command -command $command
-
- $result.arguments = $command
-
- return $result
-}
-
-function Get-NssmServiceStatus {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service
- )
-
- return Invoke-NssmCommand -arguments @("status", $service)
-}
-
-function Get-NssmServiceParameter {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service,
- [Parameter(Mandatory=$true)]
- [Alias("param")]
- [string]$parameter,
- [Parameter(Mandatory=$false)]
- [string]$subparameter
- )
-
- $arguments = @("get", $service, $parameter)
- if($subparameter -ne "") {
- $arguments += $subparameter
- }
- return Invoke-NssmCommand -arguments $arguments
-}
-
-function Set-NssmServiceParameter {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service,
- [Parameter(Mandatory=$true)]
- [string]$parameter,
- [Parameter(Mandatory=$true,ValueFromRemainingArguments=$true)]
- [Alias("value")]
- [string[]]$arguments
- )
-
- return Invoke-NssmCommand -arguments (@("set", $service, $parameter) + $arguments)
-}
-
-function Reset-NssmServiceParameter {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service,
- [Parameter(Mandatory=$true)]
- [Alias("param")]
- [string]$parameter
- )
-
- return Invoke-NssmCommand -arguments @("reset", $service, $parameter)
-}
-
-function Update-NssmServiceParameter {
- <#
- .SYNOPSIS
- A generic cmdlet to idempotently set a nssm service parameter.
- .PARAMETER service
- [String] The service name
- .PARAMETER parameter
- [String] The name of the nssm parameter to set.
- .PARAMETER arguments
- [String[]] Target value (or list of value) or array of arguments to pass to the 'nssm set' command.
- .PARAMETER compare
- [scriptblock] An optionnal idempotency check scriptblock that must return true when
- the current value is equal to the desired value. Usefull when 'nssm get' doesn't return
- the same value as 'nssm set' takes in argument, like for the ObjectName parameter.
- #>
- [CmdletBinding(SupportsShouldProcess=$true)]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service,
-
- [Parameter(Mandatory=$true)]
- [string]$parameter,
-
- [Parameter(Mandatory=$true,ValueFromRemainingArguments=$true)]
- [AllowEmptyString()]
- [AllowNull()]
- [Alias("value")]
- [string[]]$arguments,
-
- [Parameter()]
- [scriptblock]$compare = {param($actual,$expected) @(Compare-Object -ReferenceObject $actual -DifferenceObject $expected).Length -eq 0}
- )
-
- if($null -eq $arguments) { return }
- $arguments = @($arguments | Where-Object { $_ -ne '' })
-
- $nssm_result = Get-NssmServiceParameter -service $service -parameter $parameter
-
- if ($nssm_result.rc -ne 0) {
- $result.nssm_error_cmd = $nssm_result.arguments
- $result.nssm_error_log = $nssm_result.stderr
- Fail-Json -obj $result -message "Error retrieving $parameter for service ""$service"""
- }
-
- $current_values = @($nssm_result.stdout.split("`n`r") | Where-Object { $_ -ne '' })
-
- if (-not $compare.Invoke($current_values,$arguments)) {
- if ($PSCmdlet.ShouldProcess($service, "Update '$parameter' parameter")) {
- if($arguments.Count -gt 0) {
- $nssm_result = Set-NssmServiceParameter -service $service -parameter $parameter -arguments $arguments
- }
- else {
- $nssm_result = Reset-NssmServiceParameter -service $service -parameter $parameter
- }
-
- if ($nssm_result.rc -ne 0) {
- $result.nssm_error_cmd = $nssm_result.arguments
- $result.nssm_error_log = $nssm_result.stderr
- Fail-Json -obj $result -message "Error setting $parameter for service ""$service"""
- }
- }
-
- $script:diff_text += "-$parameter = $($current_values -join ', ')`n+$parameter = $($arguments -join ', ')`n"
- $result.changed_by = $parameter
- $result.changed = $true
- }
-}
-
-function Test-NssmServiceExists {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service
- )
-
- return [bool](Get-Service -Name $service -ErrorAction SilentlyContinue)
-}
-
-function Invoke-NssmStart {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service
- )
-
- $nssm_result = Invoke-NssmCommand -arguments @("start", $service)
-
- if ($nssm_result.rc -ne 0) {
- $result.nssm_error_cmd = $nssm_result.arguments
- $result.nssm_error_log = $nssm_result.stderr
- Fail-Json -obj $result -message "Error starting service ""$service"""
- }
-}
-
-function Invoke-NssmStop {
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service
- )
-
- $nssm_result = Invoke-NssmCommand -arguments @("stop", $service)
-
- if ($nssm_result.rc -ne 0) {
- $result.nssm_error_cmd = $nssm_result.arguments
- $result.nssm_error_log = $nssm_result.stderr
- Fail-Json -obj $result -message "Error stopping service ""$service"""
- }
-}
-
-function Start-NssmService {
- [CmdletBinding(SupportsShouldProcess=$true)]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service
- )
-
- $currentStatus = Get-NssmServiceStatus -service $service
-
- if ($currentStatus.rc -ne 0) {
- $result.nssm_error_cmd = $currentStatus.arguments
- $result.nssm_error_log = $currentStatus.stderr
- Fail-Json -obj $result -message "Error starting service ""$service"""
- }
-
- if ($currentStatus.stdout -notlike "*SERVICE_RUNNING*") {
- if ($PSCmdlet.ShouldProcess($service, "Start service")) {
- switch -wildcard ($currentStatus.stdout) {
- "*SERVICE_STOPPED*" { Invoke-NssmStart -service $service }
-
- "*SERVICE_CONTINUE_PENDING*" { Invoke-NssmStop -service $service; Invoke-NssmStart -service $service }
- "*SERVICE_PAUSE_PENDING*" { Invoke-NssmStop -service $service; Invoke-NssmStart -service $service }
- "*SERVICE_PAUSED*" { Invoke-NssmStop -service $service; Invoke-NssmStart -service $service }
- "*SERVICE_START_PENDING*" { Invoke-NssmStop -service $service; Invoke-NssmStart -service $service }
- "*SERVICE_STOP_PENDING*" { Invoke-NssmStop -service $service; Invoke-NssmStart -service $service }
- }
- }
-
- $result.changed_by = "start_service"
- $result.changed = $true
- }
-}
-
-function Stop-NssmService {
- [CmdletBinding(SupportsShouldProcess=$true)]
- param(
- [Parameter(Mandatory=$true)]
- [string]$service
- )
-
- $currentStatus = Get-NssmServiceStatus -service $service
-
- if ($currentStatus.rc -ne 0) {
- $result.nssm_error_cmd = $currentStatus.arguments
- $result.nssm_error_log = $currentStatus.stderr
- Fail-Json -obj $result -message "Error stopping service ""$service"""
- }
-
- if ($currentStatus.stdout -notlike "*SERVICE_STOPPED*") {
- if ($PSCmdlet.ShouldProcess($service, "Stop service")) {
- Invoke-NssmStop -service $service
- }
-
- $result.changed_by = "stop_service"
- $result.changed = $true
- }
-}
-
-if (($null -ne $appParameters) -and ($null -ne $appArguments)) {
- Fail-Json $result "'app_parameters' and 'arguments' are mutually exclusive but have both been set."
-}
-
-# Backward compatibility for old parameters style. Remove the block bellow in 2.12
-if ($null -ne $appParameters) {
- Add-DeprecationWarning -obj $result -message "The parameter 'app_parameters' will be removed soon, use 'arguments' instead" -version 2.12
-
- if ($appParameters -isnot [string]) {
- Fail-Json -obj $result -message "The app_parameters parameter must be a string representing a dictionary."
- }
-
- # Convert dict-as-string form to list
- $escapedAppParameters = $appParameters.TrimStart("@").TrimStart("{").TrimEnd("}").Replace("; ","`n").Replace("\","\\")
- $appParametersHash = ConvertFrom-StringData -StringData $escapedAppParameters
-
- $appParamsArray = @()
- $appParametersHash.GetEnumerator() | Foreach-Object {
- if ($_.Name -ne "_") {
- $appParamsArray += $_.Name
- }
- $appParamsArray += $_.Value
- }
- $appArguments = @($appParamsArray)
-
- # The rest of the code should use only the new $appArguments variable
-}
-
-if ($state -in @("started","stopped","restarted")) {
- Add-DeprecationWarning -obj $result -message "The values 'started', 'stopped', and 'restarted' for 'state' will be removed soon, use the win_service module to start or stop the service instead" -version 2.12
-}
-if ($params.ContainsKey('start_mode')) {
- Add-DeprecationWarning -obj $result -message "The parameter 'start_mode' will be removed soon, use the win_service module instead" -version 2.12
-}
-if ($null -ne $dependencies) {
- Add-DeprecationWarning -obj $result -message "The parameter 'dependencies' will be removed soon, use the win_service module instead" -version 2.12
-}
-if ($null -ne $user) {
- Add-DeprecationWarning -obj $result -message "The parameter 'user' will be removed soon, use the win_service module instead" -version 2.12
-}
-if ($null -ne $password) {
- Add-DeprecationWarning -obj $result -message "The parameter 'password' will be removed soon, use the win_service module instead" -version 2.12
-}
-
-if ($state -ne 'absent') {
- if ($null -eq $application) {
- Fail-Json -obj $result -message "The application parameter must be defined when the state is not absent."
- }
-
- if (-not (Test-Path -LiteralPath $application -PathType Leaf)) {
- Fail-Json -obj $result -message "The application specified ""$application"" does not exist on the host."
- }
-
- if($null -eq $appDirectory) {
- $appDirectory = (Get-Item -LiteralPath $application).DirectoryName
- }
-
- if ($user -and -not $password) {
- Fail-Json -obj $result -message "User without password is informed for service ""$name"""
- }
-}
-
-
-$service_exists = Test-NssmServiceExists -service $name
-
-if ($state -eq 'absent') {
- if ($service_exists) {
- if(-not $check_mode) {
- if ((Get-Service -Name $name).Status -ne "Stopped") {
- $nssm_result = Invoke-NssmStop -service $name
- }
-
- $nssm_result = Invoke-NssmCommand -arguments @("remove", $name, "confirm")
-
- if ($nssm_result.rc -ne 0) {
- $result.nssm_error_cmd = $nssm_result.arguments
- $result.nssm_error_log = $nssm_result.stderr
- Fail-Json -obj $result -message "Error removing service ""$name"""
- }
- }
-
- $diff_text += "-[$name]"
- $result.changed_by = "remove_service"
- $result.changed = $true
- }
-} else {
- $diff_text_added_prefix = ''
- if (-not $service_exists) {
- if(-not $check_mode) {
- $nssm_result = Invoke-NssmCommand -arguments @("install", $name, $application)
-
- if ($nssm_result.rc -ne 0) {
- $result.nssm_error_cmd = $nssm_result.arguments
- $result.nssm_error_log = $nssm_result.stderr
- Fail-Json -obj $result -message "Error installing service ""$name"""
- }
- $service_exists = $true
- }
-
- $diff_text_added_prefix = '+'
- $result.changed_by = "install_service"
- $result.changed = $true
- }
-
- $diff_text += "$diff_text_added_prefix[$name]`n"
-
- # We cannot configure a service that was created above in check mode as it won't actually exist
- if ($service_exists) {
- $common_params = @{
- service = $name
- WhatIf = $check_mode
- }
-
- Update-NssmServiceParameter -parameter "Application" -value $application @common_params
- Update-NssmServiceParameter -parameter "DisplayName" -value $display_name @common_params
- Update-NssmServiceParameter -parameter "Description" -value $description @common_params
-
- Update-NssmServiceParameter -parameter "AppDirectory" -value $appDirectory @common_params
-
-
- if ($null -ne $appArguments) {
- $singleLineParams = ""
- if ($appArguments -is [array]) {
- $singleLineParams = Argv-ToString -arguments $appArguments
- } else {
- $singleLineParams = $appArguments.ToString()
- }
-
- $result.nssm_app_parameters = $appArguments
- $result.nssm_single_line_app_parameters = $singleLineParams
-
- Update-NssmServiceParameter -parameter "AppParameters" -value $singleLineParams @common_params
- }
-
-
- Update-NssmServiceParameter -parameter "AppStdout" -value $stdoutFile @common_params
- Update-NssmServiceParameter -parameter "AppStderr" -value $stderrFile @common_params
-
- ###
- # Setup file rotation so we don't accidentally consume too much disk
- ###
-
- #set files to overwrite
- Update-NssmServiceParameter -parameter "AppStdoutCreationDisposition" -value 2 @common_params
- Update-NssmServiceParameter -parameter "AppStderrCreationDisposition" -value 2 @common_params
-
- #enable file rotation
- Update-NssmServiceParameter -parameter "AppRotateFiles" -value 1 @common_params
-
- #don't rotate until the service restarts
- Update-NssmServiceParameter -parameter "AppRotateOnline" -value $app_rotate_online @common_params
-
- #both of the below conditions must be met before rotation will happen
- #minimum age before rotating
- Update-NssmServiceParameter -parameter "AppRotateSeconds" -value 86400 @common_params
-
- #minimum size before rotating
- Update-NssmServiceParameter -parameter "AppRotateBytes" -value $app_rotate_bytes @common_params
-
-
- ############## DEPRECATED block since 2.8. Remove in 2.12 ##############
- Update-NssmServiceParameter -parameter "DependOnService" -arguments $dependencies @common_params
- if ($user) {
- $fullUser = $user
- if (-Not($user.contains("@")) -And ($user.Split("\").count -eq 1)) {
- $fullUser = ".\" + $user
- }
-
- # Use custom compare callback to test only the username (and not the password)
- Update-NssmServiceParameter -parameter "ObjectName" -arguments @($fullUser, $password) -compare {param($actual,$expected) $actual[0] -eq $expected[0]} @common_params
- }
- $mappedMode = $start_modes_map.$startMode
- Update-NssmServiceParameter -parameter "Start" -value $mappedMode @common_params
- if ($state -in "stopped","restarted") {
- Stop-NssmService @common_params
- }
-
- if($state -in "started","restarted") {
- Start-NssmService @common_params
- }
- ########################################################################
-
- # Added per users` requests
- if ($null -ne $app_stop_method_console)
- {
- Update-NssmServiceParameter -parameter "AppStopMethodConsole" -value $app_stop_method_console @common_params
- }
-
- if ($null -ne $app_stop_method_skip)
- {
- Update-NssmServiceParameter -parameter "AppStopMethodSkip" -value $app_stop_method_skip @common_params
- }
- }
-}
-
-if ($diff_mode -and $result.changed -eq $true) {
- $result.diff = @{
- prepared = $diff_text
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_nssm.py b/lib/ansible/modules/windows/win_nssm.py
deleted file mode 100644
index 1d15676e91..0000000000
--- a/lib/ansible/modules/windows/win_nssm.py
+++ /dev/null
@@ -1,217 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Heyo
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_nssm
-version_added: "2.0"
-short_description: Install a service using NSSM
-description:
- - Install a Windows service using the NSSM wrapper.
- - NSSM is a service helper which doesn't suck. See U(https://nssm.cc/) for more information.
-requirements:
- - "nssm >= 2.24.0 # (install via M(win_chocolatey)) C(win_chocolatey: name=nssm)"
-options:
- name:
- description:
- - Name of the service to operate on.
- type: str
- required: true
- state:
- description:
- - State of the service on the system.
- - Values C(started), C(stopped), and C(restarted) are deprecated since v2.8,
- please use the M(win_service) module instead to start, stop or restart the service.
- type: str
- choices: [ absent, present, started, stopped, restarted ]
- default: present
- application:
- description:
- - The application binary to run as a service
- - Required when I(state) is C(present), C(started), C(stopped), or C(restarted).
- type: path
- executable:
- description:
- - The location of the NSSM utility (in case it is not located in your PATH).
- type: path
- default: nssm.exe
- version_added: "2.8.0"
- description:
- description:
- - The description to set for the service.
- type: str
- version_added: "2.8.0"
- display_name:
- description:
- - The display name to set for the service.
- type: str
- version_added: "2.8.0"
- working_directory:
- version_added: "2.8.0"
- description:
- - The working directory to run the service executable from (defaults to the directory containing the application binary)
- type: path
- aliases: [ app_directory, chdir ]
- stdout_file:
- description:
- - Path to receive output.
- type: path
- stderr_file:
- description:
- - Path to receive error output.
- type: path
- app_parameters:
- description:
- - A string representing a dictionary of parameters to be passed to the application when it starts.
- - DEPRECATED since v2.8, please use I(arguments) instead.
- - This is mutually exclusive with I(arguments).
- type: str
- arguments:
- description:
- - Parameters to be passed to the application when it starts.
- - This can be either a simple string or a list.
- - This parameter was renamed from I(app_parameters_free_form) in 2.8.
- - This is mutually exclusive with I(app_parameters).
- aliases: [ app_parameters_free_form ]
- type: str
- version_added: "2.3"
- dependencies:
- description:
- - Service dependencies that has to be started to trigger startup, separated by comma.
- - DEPRECATED since v2.8, please use the M(win_service) module instead.
- type: list
- user:
- description:
- - User to be used for service startup.
- - DEPRECATED since v2.8, please use the M(win_service) module instead.
- type: str
- password:
- description:
- - Password to be used for service startup.
- - DEPRECATED since v2.8, please use the M(win_service) module instead.
- type: str
- start_mode:
- description:
- - If C(auto) is selected, the service will start at bootup.
- - C(delayed) causes a delayed but automatic start after boot (added in version 2.5).
- - C(manual) means that the service will start only when another service needs it.
- - C(disabled) means that the service will stay off, regardless if it is needed or not.
- - DEPRECATED since v2.8, please use the M(win_service) module instead.
- type: str
- choices: [ auto, delayed, disabled, manual ]
- default: auto
- app_rotate_bytes:
- description:
- - NSSM will not rotate any file which is smaller than the configured number of bytes.
- type: int
- default: 104858
- version_added: "2.10"
- app_rotate_online:
- description:
- - If set to 1, nssm can rotate files which grow to the configured file size limit while the service is running.
- type: int
- choices:
- - 0
- - 1
- default: 0
- version_added: "2.10"
- app_stop_method_console:
- description:
- - Time to wait after sending Control-C.
- type: int
- version_added: "2.10"
- app_stop_method_skip:
- description:
- - To disable service shutdown methods, set to the sum of one or more of the numbers
- - 1 - Don't send Control-C to the console.
- - 2 - Don't send WM_CLOSE to windows.
- - 4 - Don't send WM_QUIT to threads.
- - 8 - Don't call TerminateProcess().
- type: int
- choices:
- - 1
- - 2
- - 3
- - 4
- - 5
- - 6
- - 7
- - 8
- - 9
- - 10
- - 11
- - 12
- - 13
- - 14
- - 15
- version_added: "2.10"
-seealso:
- - module: win_service
-notes:
- - The service will NOT be started after its creation when C(state=present).
- - Once the service is created, you can use the M(win_service) module to start it or configure
- some additionals properties, such as its startup type, dependencies, service account, and so on.
-author:
- - Adam Keech (@smadam813)
- - George Frank (@georgefrank)
- - Hans-Joachim Kliemeck (@h0nIg)
- - Michael Wild (@themiwi)
- - Kevin Subileau (@ksubileau)
- - Shachaf Goldstein (@Shachaf92)
-'''
-
-EXAMPLES = r'''
-- name: Install the foo service
- win_nssm:
- name: foo
- application: C:\windows\foo.exe
-
-# This will yield the following command: C:\windows\foo.exe bar "true"
-- name: Install the Consul service with a list of parameters
- win_nssm:
- name: Consul
- application: C:\consul\consul.exe
- arguments:
- - agent
- - -config-dir=C:\consul\config
-
-# This is strictly equivalent to the previous example
-- name: Install the Consul service with an arbitrary string of parameters
- win_nssm:
- name: Consul
- application: C:\consul\consul.exe
- arguments: agent -config-dir=C:\consul\config
-
-
-# Install the foo service, and then configure and start it with win_service
-- name: Install the foo service, redirecting stdout and stderr to the same file
- win_nssm:
- name: foo
- application: C:\windows\foo.exe
- stdout_file: C:\windows\foo.log
- stderr_file: C:\windows\foo.log
-
-- name: Configure and start the foo service using win_service
- win_service:
- name: foo
- dependencies: [ adf, tcpip ]
- username: foouser
- password: secret
- start_mode: manual
- state: started
-
-- name: Remove the foo service
- win_nssm:
- name: foo
- state: absent
-'''
diff --git a/lib/ansible/modules/windows/win_pagefile.ps1 b/lib/ansible/modules/windows/win_pagefile.ps1
deleted file mode 100644
index 2c37f200c1..0000000000
--- a/lib/ansible/modules/windows/win_pagefile.ps1
+++ /dev/null
@@ -1,202 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Liran Nisanov <lirannis@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-########
-
-Function Remove-Pagefile($path, $whatif)
-{
- Get-CIMInstance Win32_PageFileSetting | Where-Object { $_.Name -eq $path } | Remove-CIMInstance -WhatIf:$whatif
-}
-
-Function Get-Pagefile($path)
-{
- Get-CIMInstance Win32_PageFileSetting | Where-Object { $_.Name -eq $path }
-}
-
-########
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name '_ansible_check_mode' -type 'bool' -default $false
-
-$automatic = Get-AnsibleParam -obj $params -name "automatic" -type "bool"
-$drive = Get-AnsibleParam -obj $params -name "drive" -type "str"
-$fullPath = $drive + ":\pagefile.sys"
-$initialSize = Get-AnsibleParam -obj $params -name "initial_size" -type "int"
-$maximumSize = Get-AnsibleParam -obj $params -name "maximum_size" -type "int"
-$override = Get-AnsibleParam -obj $params -name "override" -type "bool" -default $true
-$removeAll = Get-AnsibleParam -obj $params -name "remove_all" -type "bool" -default $false
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "query" -validateset "present","absent","query"
-$systemManaged = Get-AnsibleParam -obj $params -name "system_managed" -type "bool" -default $false
-$testPath = Get-AnsibleParam -obj $params -name "test_path" -type "bool" -default $true
-
-$result = @{
- changed = $false
-}
-
-if ($removeAll) {
- $currentPageFiles = Get-CIMInstance Win32_PageFileSetting
- if ($null -ne $currentPageFiles) {
- $currentPageFiles | Remove-CIMInstance -WhatIf:$check_mode > $null
- $result.changed = $true
- }
-}
-
-if ($null -ne $automatic) {
- # change autmoatic managed pagefile
- try {
- $computerSystem = Get-CIMInstance -Class win32_computersystem
- } catch {
- Fail-Json $result "Failed to query WMI computer system object $($_.Exception.Message)"
- }
- if ($computerSystem.AutomaticManagedPagefile -ne $automatic) {
- if (-not $check_mode) {
- try {
- $computerSystem | Set-CimInstance -Property @{automaticmanagedpagefile="$automatic"} > $null
- } catch {
- Fail-Json $result "Failed to set AutomaticManagedPagefile $($_.Exception.Message)"
- }
- }
- $result.changed = $true
- }
-}
-
-if ($state -eq "absent") {
- # Remove pagefile
- if ($null -ne (Get-Pagefile $fullPath))
- {
- try {
- Remove-Pagefile $fullPath -whatif:$check_mode
- } catch {
- Fail-Json $result "Failed to remove pagefile $($_.Exception.Message)"
- }
- $result.changed = $true
- }
-} elseif ($state -eq "present") {
- # Remove current pagefile
- if ($override) {
- if ($null -ne (Get-Pagefile $fullPath))
- {
- try {
- Remove-Pagefile $fullPath -whatif:$check_mode
- } catch {
- Fail-Json $result "Failed to remove current pagefile $($_.Exception.Message)"
- }
- $result.changed = $true
- }
- }
-
- # Make sure drive is accessible
- if (($test_path) -and (-not (Test-Path "${drive}:"))) {
- Fail-Json $result "Unable to access '${drive}:' drive"
- }
-
- $curPagefile = Get-Pagefile $fullPath
-
- # Set pagefile
- if ($null -eq $curPagefile) {
- try {
- $pagefile = New-CIMInstance -Class Win32_PageFileSetting -Arguments @{name = $fullPath;} -WhatIf:$check_mode
- } catch {
- Fail-Json $result "Failed to create pagefile $($_.Exception.Message)"
- }
- if (-not ($systemManaged -or $check_mode)) {
- try {
- $pagefile | Set-CimInstance -Property @{ InitialSize = $initialSize; MaximumSize = $maximumSize}
- } catch {
- $originalExceptionMessage = $($_.Exception.Message)
- # Try workaround before failing
- try {
- Remove-Pagefile $fullPath -whatif:$check_mode
- } catch {
- Fail-Json $result "Failed to remove pagefile before workaround $($_.Exception.Message) Original exception: $originalExceptionMessage"
- }
- try {
- $pagingFilesValues = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management").PagingFiles
- } catch {
- Fail-Json $result "Failed to get pagefile settings from the registry for workaround $($_.Exception.Message) Original exception: $originalExceptionMessage"
- }
- $pagingFilesValues += "$fullPath $initialSize $maximumSize"
- try {
- Set-ItemProperty -LiteralPath "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management" "PagingFiles" $pagingFilesValues
- } catch {
- Fail-Json $result "Failed to set pagefile settings to the registry for workaround $($_.Exception.Message) Original exception: $originalExceptionMessage"
- }
- }
- }
- $result.changed = $true
- }else
- {
- $CurPageFileSystemManaged = (Get-CimInstance -ClassName win32_Pagefile -Property 'System' -Filter "name='$($fullPath.Replace('\','\\'))'").System
- if ((-not $check_mode) -and
- -not ($systemManaged -or $CurPageFileSystemManaged) -and
- ( ($curPagefile.InitialSize -ne $initialSize) -or
- ($curPagefile.maximumSize -ne $maximumSize)))
- {
- $curPagefile.InitialSize = $initialSize
- $curPagefile.MaximumSize = $maximumSize
- try {
- $curPagefile.Put() | out-null
- } catch {
- $originalExceptionMessage = $($_.Exception.Message)
- # Try workaround before failing
- try {
- Remove-Pagefile $fullPath -whatif:$check_mode
- } catch {
- Fail-Json $result "Failed to remove pagefile before workaround $($_.Exception.Message) Original exception: $originalExceptionMessage"
- }
- try {
- $pagingFilesValues = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management").PagingFiles
- } catch {
- Fail-Json $result "Failed to get pagefile settings from the registry for workaround $($_.Exception.Message) Original exception: $originalExceptionMessage"
- }
- $pagingFilesValues += "$fullPath $initialSize $maximumSize"
- try {
- Set-ItemProperty -LiteralPath "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management" -Name "PagingFiles" -Value $pagingFilesValues
- } catch {
- Fail-Json $result "Failed to set pagefile settings to the registry for workaround $($_.Exception.Message) Original exception: $originalExceptionMessage"
- }
- }
- $result.changed = $true
- }
- }
-} elseif ($state -eq "query") {
- $result.pagefiles = @()
-
- if ($null -eq $drive) {
- try {
- $pagefiles = Get-CIMInstance Win32_PageFileSetting
- } catch {
- Fail-Json $result "Failed to query all pagefiles $($_.Exception.Message)"
- }
- } else {
- try {
- $pagefiles = Get-Pagefile $fullPath
- } catch {
- Fail-Json $result "Failed to query specific pagefile $($_.Exception.Message)"
- }
- }
-
- # Get all pagefiles
- foreach ($currentPagefile in $pagefiles) {
- $currentPagefileObject = @{
- name = $currentPagefile.Name
- initial_size = $currentPagefile.InitialSize
- maximum_size = $currentPagefile.MaximumSize
- caption = $currentPagefile.Caption
- description = $currentPagefile.Description
- }
- $result.pagefiles += ,$currentPagefileObject
- }
-
- # Get automatic managed pagefile state
- try {
- $result.automatic_managed_pagefiles = (Get-CIMInstance -Class win32_computersystem).AutomaticManagedPagefile
- } catch {
- Fail-Json $result "Failed to query automatic managed pagefile state $($_.Exception.Message)"
- }
-}
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_pagefile.py b/lib/ansible/modules/windows/win_pagefile.py
deleted file mode 100644
index af65d97772..0000000000
--- a/lib/ansible/modules/windows/win_pagefile.py
+++ /dev/null
@@ -1,139 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Liran Nisanov <lirannis@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_pagefile
-version_added: "2.4"
-short_description: Query or change pagefile configuration
-description:
- - Query current pagefile configuration.
- - Enable/Disable AutomaticManagedPagefile.
- - Create new or override pagefile configuration.
-options:
- drive:
- description:
- - The drive of the pagefile.
- type: str
- initial_size:
- description:
- - The initial size of the pagefile in megabytes.
- type: int
- maximum_size:
- description:
- - The maximum size of the pagefile in megabytes.
- type: int
- override:
- description:
- - Override the current pagefile on the drive.
- type: bool
- default: yes
- system_managed:
- description:
- - Configures current pagefile to be managed by the system.
- type: bool
- default: no
- automatic:
- description:
- - Configures AutomaticManagedPagefile for the entire system.
- type: bool
- remove_all:
- description:
- - Remove all pagefiles in the system, not including automatic managed.
- type: bool
- default: no
- test_path:
- description:
- - Use Test-Path on the drive to make sure the drive is accessible before creating the pagefile.
- type: bool
- default: yes
- state:
- description:
- - State of the pagefile.
- type: str
- choices: [ absent, present, query ]
- default: query
-notes:
-- There is difference between automatic managed pagefiles that configured once for the entire system and system managed pagefile that configured per pagefile.
-- InitialSize 0 and MaximumSize 0 means the pagefile is managed by the system.
-- Value out of range exception may be caused by several different issues, two common problems - No such drive, Pagefile size is too small.
-- Setting a pagefile when AutomaticManagedPagefile is on will disable the AutomaticManagedPagefile.
-author:
-- Liran Nisanov (@LiranNis)
-'''
-
-EXAMPLES = r'''
-- name: Query pagefiles configuration
- win_pagefile:
-
-- name: Query C pagefile
- win_pagefile:
- drive: C
-
-- name: Set C pagefile, don't override if exists
- win_pagefile:
- drive: C
- initial_size: 1024
- maximum_size: 1024
- override: no
- state: present
-
-- name: Set C pagefile, override if exists
- win_pagefile:
- drive: C
- initial_size: 1024
- maximum_size: 1024
- state: present
-
-- name: Remove C pagefile
- win_pagefile:
- drive: C
- state: absent
-
-- name: Remove all current pagefiles, enable AutomaticManagedPagefile and query at the end
- win_pagefile:
- remove_all: yes
- automatic: yes
-
-- name: Remove all pagefiles disable AutomaticManagedPagefile and set C pagefile
- win_pagefile:
- drive: C
- initial_size: 2048
- maximum_size: 2048
- remove_all: yes
- automatic: no
- state: present
-
-- name: Set D pagefile, override if exists
- win_pagefile:
- drive: d
- initial_size: 1024
- maximum_size: 1024
- state: present
-'''
-
-RETURN = r'''
-automatic_managed_pagefiles:
- description: Whether the pagefiles is automatically managed.
- returned: When state is query.
- type: bool
- sample: true
-pagefiles:
- description: Contains caption, description, initial_size, maximum_size and name for each pagefile in the system.
- returned: When state is query.
- type: list
- sample:
- [{"caption": "c:\\ 'pagefile.sys'", "description": "'pagefile.sys' @ c:\\", "initial_size": 2048, "maximum_size": 2048, "name": "c:\\pagefile.sys"},
- {"caption": "d:\\ 'pagefile.sys'", "description": "'pagefile.sys' @ d:\\", "initial_size": 1024, "maximum_size": 1024, "name": "d:\\pagefile.sys"}]
-
-'''
diff --git a/lib/ansible/modules/windows/win_partition.ps1 b/lib/ansible/modules/windows/win_partition.ps1
deleted file mode 100644
index 2bd1ffc0d3..0000000000
--- a/lib/ansible/modules/windows/win_partition.ps1
+++ /dev/null
@@ -1,326 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Varun Chopra (@chopraaa) <v@chopraaa.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#AnsibleRequires -OSVersion 6.2
-
-Set-StrictMode -Version 2
-
-$ErrorActionPreference = "Stop"
-
-$spec = @{
- options = @{
- state = @{ type = "str"; choices = "absent", "present"; default = "present" }
- drive_letter = @{ type = "str" }
- disk_number = @{ type = "int" }
- partition_number = @{ type = "int" }
- partition_size = @{ type = "str" }
- read_only = @{ type = "bool" }
- active = @{ type = "bool" }
- hidden = @{ type = "bool" }
- offline = @{ type = "bool" }
- mbr_type = @{ type = "str"; choices = "fat12", "fat16", "extended", "huge", "ifs", "fat32" }
- gpt_type = @{ type = "str"; choices = "system_partition", "microsoft_reserved", "basic_data", "microsoft_recovery" }
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$state = $module.Params.state
-$drive_letter = $module.Params.drive_letter
-$disk_number = $module.Params.disk_number
-$partition_number = $module.Params.partition_number
-$partition_size = $module.Params.partition_size
-$read_only = $module.Params.read_only
-$active = $module.Params.active
-$hidden = $module.Params.hidden
-$offline = $module.Params.offline
-$mbr_type = $module.Params.mbr_type
-$gpt_type = $module.Params.gpt_type
-
-$size_is_maximum = $false
-$ansible_partition = $false
-$ansible_partition_size = $null
-$partition_style = $null
-
-$gpt_styles = @{
- system_partition = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"
- microsoft_reserved = "e3c9e316-0b5c-4db8-817d-f92df00215ae"
- basic_data = "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7"
- microsoft_recovery = "de94bba4-06d1-4d40-a16a-bfd50179d6ac"
-}
-
-$mbr_styles = @{
- fat12 = 1
- fat16 = 4
- extended = 5
- huge = 6
- ifs = 7
- fat32 = 12
-}
-
-function Convert-SizeToBytes {
- param(
- $Size,
- $Units
- )
-
- switch ($Units) {
- "B" { return $Size }
- "KB" { return 1000 * $Size }
- "KiB" { return 1024 * $Size }
- "MB" { return [Math]::Pow(1000, 2) * $Size }
- "MiB" { return [Math]::Pow(1024, 2) * $Size }
- "GB" { return [Math]::Pow(1000, 3) * $Size }
- "GiB" { return [Math]::Pow(1024, 3) * $Size }
- "TB" { return [Math]::Pow(1000, 4) * $Size }
- "TiB" { return [Math]::Pow(1024, 4) * $Size }
- }
-}
-
-if ($null -ne $partition_size) {
- if ($partition_size -eq -1) {
- $size_is_maximum = $true
- }
- elseif ($partition_size -match '^(?<Size>[0-9]+)[ ]*(?<Units>b|kb|kib|mb|mib|gb|gib|tb|tib)$') {
- $ansible_partition_size = Convert-SizeToBytes -Size $Matches.Size -Units $Matches.Units
- }
- else {
- $module.FailJson("Invalid partition size. B, KB, KiB, MB, MiB, GB, GiB, TB, TiB are valid partition size units")
- }
-}
-
-# If partition_exists, we can change or delete it; otherwise we only need the disk to create a new partition
-if ($null -ne $disk_number -and $null -ne $partition_number) {
- $ansible_partition = Get-Partition -DiskNumber $disk_number -PartitionNumber $partition_number -ErrorAction SilentlyContinue
-}
-# Check if drive_letter is either auto-assigned or a character from A-Z
-elseif ($drive_letter -and -not ($disk_number -and $partition_number)) {
- if ($drive_letter -eq "auto" -or $drive_letter -match "^[a-zA-Z]$") {
- $ansible_partition = Get-Partition -DriveLetter $drive_letter -ErrorAction SilentlyContinue
- }
- else {
- $module.FailJson("Incorrect usage of drive_letter: specify a drive letter from A-Z or use 'auto' to automatically assign a drive letter")
- }
-}
-elseif ($disk_number) {
- try {
- Get-Disk -Number $disk_number | Out-Null
- } catch {
- $module.FailJson("Specified disk does not exist")
- }
-}
-else {
- $module.FailJson("You must provide disk_number, partition_number")
-}
-
-# Partition can't have two partition styles
-if ($null -ne $gpt_type -and $null -ne $mbr_type) {
- $module.FailJson("Cannot specify both GPT and MBR partition styles. Check which partition style is supported by the disk")
-}
-
-function New-AnsiblePartition {
- param(
- $DiskNumber,
- $Letter,
- $SizeMax,
- $Size,
- $MbrType,
- $GptType,
- $Style
- )
-
- $parameters = @{
- DiskNumber = $DiskNumber
- }
-
- if ($null -ne $Letter) {
- switch ($Letter) {
- "auto" {
- $parameters.Add("AssignDriveLetter", $True)
- }
- default {
- $parameters.Add("DriveLetter", $Letter)
- }
- }
- }
-
- if ($null -ne $Size) {
- $parameters.Add("Size", $Size)
- }
-
- if ($null -ne $MbrType) {
- $parameters.Add("MbrType", $Style)
- }
-
- if ($null -ne $GptType) {
- $parameters.Add("GptType", $Style)
- }
-
- try {
- $new_partition = New-Partition @parameters
- } catch {
- $module.FailJson("Unable to create a new partition: $($_.Exception.Message)", $_)
- }
-
- return $new_partition
-}
-
-
-function Set-AnsiblePartitionState {
- param(
- $hidden,
- $read_only,
- $active,
- $partition
- )
-
- $parameters = @{
- DiskNumber = $partition.DiskNumber
- PartitionNumber = $partition.PartitionNumber
- }
-
- if ($hidden -NotIn ($null, $partition.IsHidden)) {
- $parameters.Add("IsHidden", $hidden)
- }
-
- if ($read_only -NotIn ($null, $partition.IsReadOnly)) {
- $parameters.Add("IsReadOnly", $read_only)
- }
-
- if ($active -NotIn ($null, $partition.IsActive)) {
- $parameters.Add("IsActive", $active)
- }
-
- try {
- Set-Partition @parameters
- } catch {
- $module.FailJson("Error changing state of partition: $($_.Exception.Message)", $_)
- }
-}
-
-
-if ($ansible_partition) {
- if ($state -eq "absent") {
- try {
- Remove-Partition -DiskNumber $ansible_partition.DiskNumber -PartitionNumber $ansible_partition.PartitionNumber -Confirm:$false -WhatIf:$module.CheckMode
- } catch {
- $module.FailJson("There was an error removing the partition: $($_.Exception.Message)", $_)
- }
- $module.Result.changed = $true
- }
- else {
-
- if ($null -ne $gpt_type -and $gpt_styles.$gpt_type -ne $ansible_partition.GptType) {
- $module.FailJson("gpt_type is not a valid parameter for existing partitions")
- }
- if ($null -ne $mbr_type -and $mbr_styles.$mbr_type -ne $ansible_partition.MbrType) {
- $module.FailJson("mbr_type is not a valid parameter for existing partitions")
- }
-
- if ($partition_size) {
- try {
- $max_supported_size = (Get-PartitionSupportedSize -DiskNumber $ansible_partition.DiskNumber -PartitionNumber $ansible_partition.PartitionNumber).SizeMax
- } catch {
- $module.FailJson("Unable to get maximum supported partition size: $($_.Exception.Message)", $_)
- }
- if ($size_is_maximum) {
- $ansible_partition_size = $max_supported_size
- }
- if ($ansible_partition_size -ne $ansible_partition.Size -and ($ansible_partition_size - $ansible_partition.Size -gt 1049000 -or $ansible_partition.Size - $ansible_partition_size -gt 1049000)) {
- if ($ansible_partition.IsReadOnly) {
- $module.FailJson("Unable to resize partition: Partition is read only")
- } else {
- try {
- Resize-Partition -DiskNumber $ansible_partition.DiskNumber -PartitionNumber $ansible_partition.PartitionNumber -Size $ansible_partition_size -WhatIf:$module.CheckMode
- } catch {
- $module.FailJson("Unable to change partition size: $($_.Exception.Message)", $_)
- }
- $module.Result.changed = $true
- }
- } elseif ($ansible_partition_size -gt $max_supported_size) {
- $module.FailJson("Specified partition size exceeds size supported by the partition")
- }
- }
-
- if ($drive_letter -NotIn ("auto", $null, $ansible_partition.DriveLetter)) {
- if (-not $module.CheckMode) {
- try {
- Set-Partition -DiskNumber $ansible_partition.DiskNumber -PartitionNumber $ansible_partition.PartitionNumber -NewDriveLetter $drive_letter
- } catch {
- $module.FailJson("Unable to change drive letter: $($_.Exception.Message)", $_)
- }
- }
- $module.Result.changed = $true
- }
- }
-}
-else {
- if ($state -eq "present") {
- if ($null -eq $disk_number) {
- $module.FailJson("Missing required parameter: disk_number")
- }
- if ($null -eq $ansible_partition_size -and -not $size_is_maximum){
- $module.FailJson("Missing required parameter: partition_size")
- }
- if (-not $size_is_maximum) {
- try {
- $max_supported_size = (Get-Disk -Number $disk_number).LargestFreeExtent
- } catch {
- $module.FailJson("Unable to get maximum size supported by disk: $($_.Exception.Message)", $_)
- }
-
- if ($ansible_partition_size -gt $max_supported_size) {
- $module.FailJson("Partition size is not supported by disk. Use partition_size: -1 to get maximum size")
- }
- } else {
- $ansible_partition_size = (Get-Disk -Number $disk_number).LargestFreeExtent
- }
-
- $supp_part_type = (Get-Disk -Number $disk_number).PartitionStyle
- if ($null -ne $mbr_type) {
- if ($supp_part_type -eq "MBR" -and $mbr_styles.ContainsKey($mbr_type)) {
- $partition_style = $mbr_styles.$mbr_type
- } else {
- $module.FailJson("Incorrect partition style specified")
- }
- }
- if ($null -ne $gpt_type) {
- if ($supp_part_type -eq "GPT" -and $gpt_styles.ContainsKey($gpt_type)) {
- $partition_style = $gpt_styles.$gpt_type
- } else {
- $module.FailJson("Incorrect partition style specified")
- }
- }
-
- if (-not $module.CheckMode) {
- $ansible_partition = New-AnsiblePartition -DiskNumber $disk_number -Letter $drive_letter -Size $ansible_partition_size -MbrType $mbr_type -GptType $gpt_type -Style $partition_style
- }
- $module.Result.changed = $true
- }
-}
-
-if ($state -eq "present" -and $ansible_partition) {
- if ($offline -NotIn ($null, $ansible_partition.IsOffline)) {
- if (-not $module.CheckMode) {
- try {
- Set-Partition -DiskNumber $ansible_partition.DiskNumber -PartitionNumber $ansible_partition.PartitionNumber -IsOffline $offline
- } catch {
- $module.FailJson("Error setting partition offline: $($_.Exception.Message)", $_)
- }
- }
- $module.Result.changed = $true
- }
-
- if ($hidden -NotIn ($null, $ansible_partition.IsHidden) -or $read_only -NotIn ($null, $ansible_partition.IsReadOnly) -or $active -NotIn ($null, $ansible_partition.IsActive)) {
- if (-not $module.CheckMode) {
- Set-AnsiblePartitionState -hidden $hidden -read_only $read_only -active $active -partition $ansible_partition
- }
- $module.Result.changed = $true
- }
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_partition.py b/lib/ansible/modules/windows/win_partition.py
deleted file mode 100644
index 18d45282d4..0000000000
--- a/lib/ansible/modules/windows/win_partition.py
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Varun Chopra (@chopraaa) <v@chopraaa.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = r'''
----
-module: win_partition
-version_added: '2.8'
-short_description: Creates, changes and removes partitions on Windows Server
-description:
- - The M(win_partition) module can create, modify or delete a partition on a disk
-options:
- state:
- description:
- - Used to specify the state of the partition. Use C(absent) to specify if a partition should be removed
- and C(present) to specify if the partition should be created or updated.
- type: str
- choices: [ absent, present]
- default: present
- drive_letter:
- description:
- - Used for accessing partitions if I(disk_number) and I(partition_number) are not provided.
- - Use C(auto) for automatically assigning a drive letter, or a letter A-Z for manually assigning a drive letter to a new partition.
- If not specified, no drive letter is assigned when creating a new partition.
- type: str
- disk_number:
- description:
- - Disk number is mandatory for creating new partitions.
- - A combination of I(disk_number) and I(partition_number) can be used to specify the partition instead of I(drive_letter) if required.
- type: int
- partition_number:
- description:
- - Used in conjunction with I(disk_number) to uniquely identify a partition.
- type: int
- partition_size:
- description:
- - Specify size of the partition in B, KB, KiB, MB, MiB, GB, GiB, TB or TiB. Use -1 to specify maximum supported size.
- - Partition size is mandatory for creating a new partition but not for updating or deleting a partition.
- - The decimal SI prefixes kilo, mega, giga, tera, etc., are powers of 10^3 = 1000. The binary prefixes kibi, mebi, gibi, tebi, etc.
- respectively refer to the corresponding power of 2^10 = 1024.
- Thus, a gigabyte (GB) is 1000000000 (1000^3) bytes while 1 gibibyte (GiB) is 1073741824 (1024^3) bytes.
- type: str
- read_only:
- description:
- - Make the partition read only, restricting changes from being made to the partition.
- type: bool
- active:
- description:
- - Specifies if the partition is active and can be used to start the system. This property is only valid when the disk's partition style is MBR.
- type: bool
- hidden:
- description:
- - Hides the target partition, making it undetectable by the mount manager.
- type: bool
- offline:
- description:
- - Sets the partition offline.
- - Adding a mount point (such as a drive letter) will cause the partition to go online again.
- type: bool
- required: no
- mbr_type:
- description:
- - Specify the partition's MBR type if the disk's partition style is MBR.
- - This only applies to new partitions.
- - This does not relate to the partitions file system formatting.
- type: str
- choices: [ fat12, fat16, extended, huge, ifs, fat32 ]
- gpt_type:
- description:
- - Specify the partition's GPT type if the disk's partition style is GPT.
- - This only applies to new partitions.
- - This does not relate to the partitions file system formatting.
- type: str
- choices: [ system_partition, microsoft_reserved, basic_data, microsoft_recovery ]
-
-notes:
- - A minimum Operating System Version of 6.2 is required to use this module. To check if your OS is compatible, see
- U(https://docs.microsoft.com/en-us/windows/desktop/sysinfo/operating-system-version).
- - This module cannot be used for removing the drive letter associated with a partition, initializing a disk or, file system formatting.
- - Idempotence works only if you're specifying a drive letter or other unique attributes such as a combination of disk number and partition number.
- - For more information, see U(https://msdn.microsoft.com/en-us/library/windows/desktop/hh830524.aspx).
-author:
- - Varun Chopra (@chopraaa) <v@chopraaa.com>
-'''
-
-EXAMPLES = r'''
-- name: Create a partition with drive letter D and size 5 GiB
- win_partition:
- drive_letter: D
- partition_size: 5 GiB
- disk_number: 1
-
-- name: Resize previously created partition to it's maximum size and change it's drive letter to E
- win_partition:
- drive_letter: E
- partition_size: -1
- partition_number: 1
- disk_number: 1
-
-- name: Delete partition
- win_partition:
- disk_number: 1
- partition_number: 1
- state: absent
-'''
-
-RETURN = r'''
-#
-'''
diff --git a/lib/ansible/modules/windows/win_pester.ps1 b/lib/ansible/modules/windows/win_pester.ps1
deleted file mode 100644
index f3f2ebdced..0000000000
--- a/lib/ansible/modules/windows/win_pester.ps1
+++ /dev/null
@@ -1,116 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Erwan Quelin (@equelin) <erwan.quelin@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-$spec = @{
- options = @{
- output_file = @{ type = "str" }
- output_format = @{ type = "str"; default = "NunitXML" }
- path = @{ type = "str"; required = $true }
- tags = @{ type = "list"; elements = "str" }
- test_parameters = @{ type = "dict" }
- version = @{ type = "str"; aliases = @(,"minimum_version") }
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$output_file = $module.Params.output_file
-$output_format = $module.Params.output_format
-$path = $module.Params.path
-$tags = $module.Params.tags
-$test_parameters = $module.Params.test_parameters
-$version = $module.Params.version
-
-Try {
- $version = [version]$version
-}
-Catch {
- $module.FailJson("Value '$version' for parameter 'minimum_version' is not a valid version format")
-}
-
-# Make sure path is a real path
-Try {
- $path = $path.TrimEnd("\")
- $path = (Get-item -LiteralPath $path).FullName
-}
-Catch {
- $module.FailJson("Cannot find file or directory: '$path' as it does not exist")
-}
-
-# Import Pester module if available
-$Pester = 'Pester'
-
-If (-not (Get-Module -Name $Pester -ErrorAction SilentlyContinue)) {
- If (Get-Module -Name $Pester -ListAvailable -ErrorAction SilentlyContinue) {
- Import-Module $Pester
- } else {
- $module.FailJson("Cannot find module: $Pester. Check if pester is installed, and if it is not, install using win_psmodule or win_chocolatey.")
- }
-}
-
-# Add actual pester's module version in the ansible's result variable
-$Pester_version = (Get-Module -Name $Pester).Version.ToString()
-$module.Result.pester_version = $Pester_version
-
-# Test if the Pester module is available with a version greater or equal than the one specified in the $version parameter
-If ((-not (Get-Module -Name $Pester -ErrorAction SilentlyContinue | Where-Object {$_.Version -ge $version})) -and ($version)) {
- $module.FailJson("$Pester version is not greater or equal to $version")
-}
-
-#Prepare Invoke-Pester parameters depending of the Pester's version.
-#Invoke-Pester output deactivation behave differently depending on the Pester's version
-If ($module.Result.pester_version -ge "4.0.0") {
- $Parameters = @{
- "show" = "none"
- "PassThru" = $True
- }
-} else {
- $Parameters = @{
- "quiet" = $True
- "PassThru" = $True
- }
-}
-
-if($tags.count){
- $Parameters.Tag = $tags
-}
-
-if($output_file){
- $Parameters.OutputFile = $output_file
- $Parameters.OutputFormat = $output_format
-}
-
-# Run Pester tests
-If (Test-Path -LiteralPath $path -PathType Leaf) {
- $test_parameters_check_mode_msg = ''
- if ($test_parameters.keys.count) {
- $Parameters.Script = @{Path = $Path ; Parameters = $test_parameters }
- $test_parameters_check_mode_msg = " with $($test_parameters.keys -join ',') parameters"
- }
- else {
- $Parameters.Script = $Path
- }
-
- if ($module.CheckMode) {
- $module.Result.output = "Run pester test in the file: $path$test_parameters_check_mode_msg"
- } else {
- $module.Result.output = Invoke-Pester @Parameters
- }
-} else {
- $Parameters.Script = $path
-
- if ($module.CheckMode) {
- $module.Result.output = "Run Pester test(s): $path"
- } else {
- $module.Result.output = Invoke-Pester @Parameters
- }
-}
-
-$module.Result.changed = $true
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_pester.py b/lib/ansible/modules/windows/win_pester.py
deleted file mode 100644
index c17009fb70..0000000000
--- a/lib/ansible/modules/windows/win_pester.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-
-DOCUMENTATION = r'''
----
-module: win_pester
-short_description: Run Pester tests on Windows hosts
-version_added: "2.6"
-description:
- - Run Pester tests on Windows hosts.
- - Test files have to be available on the remote host.
-requirements:
- - Pester
-options:
- path:
- description:
- - Path to a pester test file or a folder where tests can be found.
- - If the path is a folder, the module will consider all ps1 files as Pester tests.
- type: str
- required: true
- tags:
- description:
- - Runs only tests in Describe blocks with specified Tags values.
- - Accepts multiple comma separated tags.
- type: list
- version_added: '2.9'
- output_file:
- description:
- - Generates an output test report.
- type: str
- version_added: '2.10'
- output_format:
- description:
- - Format of the test report to be generated.
- - This parameter is to be used with output_file option.
- type: str
- default: NunitXML
- version_added: '2.10'
- test_parameters:
- description:
- - Allows to specify parameters to the test script.
- type: dict
- version_added: '2.9'
- version:
- description:
- - Minimum version of the pester module that has to be available on the remote host.
- type: str
- aliases:
- - minimum_version
-author:
- - Erwan Quelin (@equelin)
- - Prasoon Karunan V (@prasoonkarunan)
-'''
-
-EXAMPLES = r'''
-- name: Get facts
- setup:
-
-- name: Add Pester module
- action:
- module_name: "{{ 'win_psmodule' if ansible_powershell_version >= 5 else 'win_chocolatey' }}"
- name: Pester
- state: present
-
-- name: Run the pester test provided in the path parameter.
- win_pester:
- path: C:\Pester
-
-- name: Run the pester tests only for the tags specified.
- win_pester:
- path: C:\Pester\TestScript.tests
- tags: CI,UnitTests
-
-# Run pesters tests files that are present in the specified folder
-# ensure that the pester module version available is greater or equal to the version parameter.
-- name: Run the pester test present in a folder and check the Pester module version.
- win_pester:
- path: C:\Pester\test01.test.ps1
- version: 4.1.0
-
-- name: Run the pester test present in a folder with given script parameters.
- win_pester:
- path: C:\Pester\test04.test.ps1
- test_parameters:
- Process: lsass
- Service: bits
-
-- name: Run the pester test present in a folder and generate NunitXML test result..
- win_pester:
- path: C:\Pester\test04.test.ps1
- output_file: c:\Pester\resullt\testresult.xml
-'''
-
-RETURN = r'''
-pester_version:
- description: Version of the pester module found on the remote host.
- returned: always
- type: str
- sample: 4.3.1
-output:
- description: Results of the Pester tests.
- returned: success
- type: list
- sample: false
-'''
diff --git a/lib/ansible/modules/windows/win_power_plan.ps1 b/lib/ansible/modules/windows/win_power_plan.ps1
deleted file mode 100644
index 9c4a871c39..0000000000
--- a/lib/ansible/modules/windows/win_power_plan.ps1
+++ /dev/null
@@ -1,207 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.AddType
-
-$spec = @{
- options = @{
- name = @{ type = "str"; required = $true }
- }
- supports_check_mode = $true
-}
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$name = $module.Params.name
-
-$module.Result.power_plan_name = $name
-$module.Result.power_plan_enabled = $null
-$module.Result.all_available_plans = $null
-
-Add-CSharpType -References @"
-using System;
-using System.Runtime.InteropServices;
-
-namespace Ansible.WinPowerPlan
-{
- public enum AccessFlags : uint
- {
- AccessScheme = 16,
- AccessSubgroup = 17,
- AccessIndividualSetting = 18
- }
-
- public class NativeMethods
- {
- [DllImport("Kernel32.dll", SetLastError = true)]
- public static extern IntPtr LocalFree(
- IntPtr hMen);
-
- [DllImport("PowrProf.dll")]
- public static extern UInt32 PowerEnumerate(
- IntPtr RootPowerKey,
- IntPtr SchemeGuid,
- IntPtr SubGroupOfPowerSettingsGuid,
- AccessFlags AccessFlags,
- UInt32 Index,
- IntPtr Buffer,
- ref UInt32 BufferSize);
-
- [DllImport("PowrProf.dll")]
- public static extern UInt32 PowerGetActiveScheme(
- IntPtr UserRootPowerKey,
- out IntPtr ActivePolicyGuid);
-
- [DllImport("PowrProf.dll")]
- public static extern UInt32 PowerReadFriendlyName(
- IntPtr RootPowerKey,
- Guid SchemeGuid,
- IntPtr SubGroupOfPowerSettingsGuid,
- IntPtr PowerSettingGuid,
- IntPtr Buffer,
- ref UInt32 BufferSize);
-
- [DllImport("PowrProf.dll")]
- public static extern UInt32 PowerSetActiveScheme(
- IntPtr UserRootPowerKey,
- Guid SchemeGuid);
- }
-}
-"@
-
-Function Get-LastWin32ErrorMessage {
- param([Int]$ErrorCode)
- $exp = New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $ErrorCode
- $error_msg = "{0} - (Win32 Error Code {1} - 0x{1:X8})" -f $exp.Message, $ErrorCode
- return $error_msg
-}
-
-Function Get-PlanName {
- param([Guid]$Plan)
-
- $buffer_size = 0
- $buffer = [IntPtr]::Zero
- [Ansible.WinPowerPlan.NativeMethods]::PowerReadFriendlyName([IntPtr]::Zero, $Plan, [IntPtr]::Zero, [IntPtr]::Zero,
- $buffer, [ref]$buffer_size) > $null
-
- $buffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($buffer_size)
- try {
- $res = [Ansible.WinPowerPlan.NativeMethods]::PowerReadFriendlyName([IntPtr]::Zero, $Plan, [IntPtr]::Zero,
- [IntPtr]::Zero, $buffer, [ref]$buffer_size)
-
- if ($res -ne 0) {
- $err_msg = Get-LastWin32ErrorMessage -ErrorCode $res
- $module.FailJson("Failed to get name for power scheme $Plan - $err_msg")
- }
-
- return [System.Runtime.InteropServices.Marshal]::PtrToStringUni($buffer)
- } finally {
- [System.Runtime.InteropServices.Marshal]::FreeHGlobal($buffer)
- }
-}
-
-Function Get-PowerPlans {
- $plans = @{}
-
- $i = 0
- while ($true) {
- $buffer_size = 0
- $buffer = [IntPtr]::Zero
- $res = [Ansible.WinPowerPlan.NativeMethods]::PowerEnumerate([IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero,
- [Ansible.WinPowerPlan.AccessFlags]::AccessScheme, $i, $buffer, [ref]$buffer_size)
-
- if ($res -eq 259) {
- # 259 == ERROR_NO_MORE_ITEMS, there are no more power plans to enumerate
- break
- } elseif ($res -notin @(0, 234)) {
- # 0 == ERROR_SUCCESS and 234 == ERROR_MORE_DATA
- $err_msg = Get-LastWin32ErrorMessage -ErrorCode $res
- $module.FailJson("Failed to get buffer size on local power schemes at index $i - $err_msg")
- }
-
- $buffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($buffer_size)
- try {
- $res = [Ansible.WinPowerPlan.NativeMethods]::PowerEnumerate([IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero,
- [Ansible.WinPowerPlan.AccessFlags]::AccessScheme, $i, $buffer, [ref]$buffer_size)
-
- if ($res -eq 259) {
- # Server 2008 does not return 259 in the first call above so we do an additional check here
- break
- } elseif ($res -notin @(0, 234, 259)) {
- $err_msg = Get-LastWin32ErrorMessage -ErrorCode $res
- $module.FailJson("Failed to enumerate local power schemes at index $i - $err_msg")
- }
- $scheme_guid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($buffer, [Type][Guid])
- } finally {
- [System.Runtime.InteropServices.Marshal]::FreeHGlobal($buffer)
- }
- $scheme_name = Get-PlanName -Plan $scheme_guid
- $plans.$scheme_name = $scheme_guid
-
- $i += 1
- }
-
- return $plans
-}
-
-Function Get-ActivePowerPlan {
- $buffer = [IntPtr]::Zero
- $res = [Ansible.WinPowerPlan.NativeMethods]::PowerGetActiveScheme([IntPtr]::Zero, [ref]$buffer)
- if ($res -ne 0) {
- $err_msg = Get-LastWin32ErrorMessage -ErrorCode $res
- $module.FailJson("Failed to get the active power plan - $err_msg")
- }
-
- try {
- $active_guid = [System.Runtime.InteropServices.Marshal]::PtrToStructure($buffer, [Type][Guid])
- } finally {
- [Ansible.WinPowerPlan.NativeMethods]::LocalFree($buffer) > $null
- }
-
- return $active_guid
-}
-
-Function Set-ActivePowerPlan {
- [CmdletBinding(SupportsShouldProcess=$true)]
- param([Guid]$Plan)
-
- $res = 0
- if ($PSCmdlet.ShouldProcess($Plan, "Set Power Plan")) {
- $res = [Ansible.WinPowerPlan.NativeMethods]::PowerSetActiveScheme([IntPtr]::Zero, $Plan)
- }
-
- if ($res -ne 0) {
- $err_msg = Get-LastWin32ErrorMessage -ErrorCode $res
- $module.FailJson("Failed to set the active power plan to $Plan - $err_msg")
- }
-}
-
-# Get all local power plans and the current active plan
-$plans = Get-PowerPlans
-$active_plan = Get-ActivePowerPlan
-$module.Result.all_available_plans = @{}
-foreach ($plan_info in $plans.GetEnumerator()) {
- $module.Result.all_available_plans.($plan_info.Key) = $plan_info.Value -eq $active_plan
-}
-
-if ($name -notin $plans.Keys) {
- $module.FailJson("Defined power_plan: ($name) is not available")
-}
-$plan_guid = $plans.$name
-$is_active = $active_plan -eq $plans.$name
-$module.Result.power_plan_enabled = $is_active
-
-if (-not $is_active) {
- Set-ActivePowerPlan -Plan $plan_guid -WhatIf:$module.CheckMode
- $module.Result.changed = $true
- $module.Result.power_plan_enabled = $true
- foreach ($plan_info in $plans.GetEnumerator()) {
- $is_active = $plan_info.Value -eq $plan_guid
- $module.Result.all_available_plans.($plan_info.Key) = $is_active
- }
-}
-
-$module.ExitJson()
-
diff --git a/lib/ansible/modules/windows/win_power_plan.py b/lib/ansible/modules/windows/win_power_plan.py
deleted file mode 100644
index 6f358993cc..0000000000
--- a/lib/ansible/modules/windows/win_power_plan.py
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_power_plan
-short_description: Changes the power plan of a Windows system
-description:
- - This module will change the power plan of a Windows system to the defined string.
- - Windows defaults to C(balanced) which will cause CPU throttling. In some cases it can be preferable
- to change the mode to C(high performance) to increase CPU performance.
-version_added: "2.4"
-options:
- name:
- description:
- - String value that indicates the desired power plan.
- - The power plan must already be present on the system.
- - Commonly there will be options for C(balanced) and C(high performance).
- type: str
- required: yes
-author:
- - Noah Sparks (@nwsparks)
-'''
-
-EXAMPLES = r'''
-- name: Change power plan to high performance
- win_power_plan:
- name: high performance
-'''
-
-RETURN = r'''
-power_plan_name:
- description: Value of the intended power plan.
- returned: always
- type: str
- sample: balanced
-power_plan_enabled:
- description: State of the intended power plan.
- returned: success
- type: bool
- sample: true
-all_available_plans:
- description: The name and enabled state of all power plans.
- returned: always
- type: dict
- sample: |
- {
- "High performance": false,
- "Balanced": true,
- "Power saver": false
- }
-'''
diff --git a/lib/ansible/modules/windows/win_product_facts.ps1 b/lib/ansible/modules/windows/win_product_facts.ps1
deleted file mode 100644
index 2fbf334119..0000000000
--- a/lib/ansible/modules/windows/win_product_facts.ps1
+++ /dev/null
@@ -1,85 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-# This modules does not accept any options
-$spec = @{
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-# First try to find the product key from ACPI
-try {
- $product_key = (Get-CimInstance -Class SoftwareLicensingService).OA3xOriginalProductKey
-} catch {
- $product_key = $null
-}
-
-if (-not $product_key) {
- # Else try to get it from the registry instead
- try {
- $data = Get-ItemPropertyValue -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion" -Name DigitalProductId
- } catch {
- $data = $null
- }
-
- # And for Windows 2008 R2
- if (-not $data) {
- try {
- $data = Get-ItemPropertyValue -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion" -Name DigitalProductId4
- } catch {
- $data = $null
- }
- }
-
- if ($data) {
- $product_key = $null
- $hexdata = $data[52..66]
- $chardata = "B","C","D","F","G","H","J","K","M","P","Q","R","T","V","W","X","Y","2","3","4","6","7","8","9"
-
- # Decode base24 binary data
- for ($i = 24; $i -ge 0; $i--) {
- $k = 0
- for ($j = 14; $j -ge 0; $j--) {
- $k = $k * 256 -bxor $hexdata[$j]
- $hexdata[$j] = [math]::truncate($k / 24)
- $k = $k % 24
- }
- $product_key = $chardata[$k] + $product_key
- if (($i % 5 -eq 0) -and ($i -ne 0)) {
- $product_key = "-" + $product_key
- }
- }
- }
-}
-
-# Retrieve license information
-$license_info = Get-CimInstance SoftwareLicensingProduct | Where-Object PartialProductKey
-
-$winlicense_status = switch ($license_info.LicenseStatus) {
- 0 { "Unlicensed" }
- 1 { "Licensed" }
- 2 { "OOBGrace" }
- 3 { "OOTGrace" }
- 4 { "NonGenuineGrace" }
- 5 { "Notification" }
- 6 { "ExtendedGrace" }
- default { $null }
-}
-
-$winlicense_edition = $license_info.Name
-$winlicense_channel = $license_info.ProductKeyChannel
-
-$module.Result.ansible_facts = @{
- ansible_os_product_id = (Get-CimInstance Win32_OperatingSystem).SerialNumber
- ansible_os_product_key = $product_key
- ansible_os_license_edition = $winlicense_edition
- ansible_os_license_channel = $winlicense_channel
- ansible_os_license_status = $winlicense_status
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_product_facts.py b/lib/ansible/modules/windows/win_product_facts.py
deleted file mode 100644
index a85ffe8dec..0000000000
--- a/lib/ansible/modules/windows/win_product_facts.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_product_facts
-short_description: Provides Windows product and license information
-description:
-- Provides Windows product and license information.
-version_added: '2.5'
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-EXAMPLES = r'''
-- name: Get product id and product key
- win_product_facts:
-
-- name: Display Windows edition
- debug:
- var: ansible_os_license_edition
-
-- name: Display Windows license status
- debug:
- var: ansible_os_license_status
-'''
-
-RETURN = r'''
-ansible_facts:
- description: Dictionary containing all the detailed information about the Windows product and license.
- returned: always
- type: complex
- contains:
- ansible_os_license_channel:
- description: The Windows license channel.
- returned: always
- type: str
- sample: Volume:MAK
- version_added: '2.8'
- ansible_os_license_edition:
- description: The Windows license edition.
- returned: always
- type: str
- sample: Windows(R) ServerStandard edition
- version_added: '2.8'
- ansible_os_license_status:
- description: The Windows license status.
- returned: always
- type: str
- sample: Licensed
- version_added: '2.8'
- ansible_os_product_id:
- description: The Windows product ID.
- returned: always
- type: str
- sample: 00326-10000-00000-AA698
- ansible_os_product_key:
- description: The Windows product key.
- returned: always
- type: str
- sample: T49TD-6VFBW-VV7HY-B2PXY-MY47H
-'''
diff --git a/lib/ansible/modules/windows/win_psexec.ps1 b/lib/ansible/modules/windows/win_psexec.ps1
deleted file mode 100644
index 04a512706e..0000000000
--- a/lib/ansible/modules/windows/win_psexec.ps1
+++ /dev/null
@@ -1,152 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.ArgvParser
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-
-# See also: https://technet.microsoft.com/en-us/sysinternals/pxexec.aspx
-
-$spec = @{
- options = @{
- command = @{ type='str'; required=$true }
- executable = @{ type='path'; default='psexec.exe' }
- hostnames = @{ type='list' }
- username = @{ type='str' }
- password = @{ type='str'; no_log=$true }
- chdir = @{ type='path' }
- wait = @{ type='bool'; default=$true }
- nobanner = @{ type='bool'; default=$false }
- noprofile = @{ type='bool'; default=$false }
- elevated = @{ type='bool'; default=$false }
- limited = @{ type='bool'; default=$false }
- system = @{ type='bool'; default=$false }
- interactive = @{ type='bool'; default=$false }
- session = @{ type='int' }
- priority = @{ type='str'; choices=@( 'background', 'low', 'belownormal', 'abovenormal', 'high', 'realtime' ) }
- timeout = @{ type='int' }
- }
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$command = $module.Params.command
-$executable = $module.Params.executable
-$hostnames = $module.Params.hostnames
-$username = $module.Params.username
-$password = $module.Params.password
-$chdir = $module.Params.chdir
-$wait = $module.Params.wait
-$nobanner = $module.Params.nobanner
-$noprofile = $module.Params.noprofile
-$elevated = $module.Params.elevated
-$limited = $module.Params.limited
-$system = $module.Params.system
-$interactive = $module.Params.interactive
-$session = $module.Params.session
-$priority = $module.Params.Priority
-$timeout = $module.Params.timeout
-
-$module.Result.changed = $true
-
-If (-Not (Get-Command $executable -ErrorAction SilentlyContinue)) {
- $module.FailJson("Executable '$executable' was not found.")
-}
-
-$arguments = [System.Collections.Generic.List`1[String]]@($executable)
-
-If ($nobanner -eq $true) {
- $arguments.Add("-nobanner")
-}
-
-# Support running on local system if no hostname is specified
-If ($hostnames) {
- $hostname_argument = ($hostnames | sort -Unique) -join ','
- $arguments.Add("\\$hostname_argument")
-}
-
-# Username is optional
-If ($null -ne $username) {
- $arguments.Add("-u")
- $arguments.Add($username)
-}
-
-# Password is optional
-If ($null -ne $password) {
- $arguments.Add("-p")
- $arguments.Add($password)
-}
-
-If ($null -ne $chdir) {
- $arguments.Add("-w")
- $arguments.Add($chdir)
-}
-
-If ($wait -eq $false) {
- $arguments.Add("-d")
-}
-
-If ($noprofile -eq $true) {
- $arguments.Add("-e")
-}
-
-If ($elevated -eq $true) {
- $arguments.Add("-h")
-}
-
-If ($system -eq $true) {
- $arguments.Add("-s")
-}
-
-If ($interactive -eq $true) {
- $arguments.Add("-i")
- If ($null -ne $session) {
- $arguments.Add($session)
- }
-}
-
-If ($limited -eq $true) {
- $arguments.Add("-l")
-}
-
-If ($null -ne $priority) {
- $arguments.Add("-$priority")
-}
-
-If ($null -ne $timeout) {
- $arguments.Add("-n")
- $arguments.Add($timeout)
-}
-
-$arguments.Add("-accepteula")
-
-$argument_string = Argv-ToString -arguments $arguments
-
-# Add the command at the end of the argument string, we don't want to escape
-# that as psexec doesn't expect it to be one arg
-$argument_string += " $command"
-
-$start_datetime = [DateTime]::UtcNow
-$module.Result.psexec_command = $argument_string
-
-$command_result = Run-Command -command $argument_string
-
-$end_datetime = [DateTime]::UtcNow
-
-$module.Result.stdout = $command_result.stdout
-$module.Result.stderr = $command_result.stderr
-
-If ($wait -eq $true) {
- $module.Result.rc = $command_result.rc
-} else {
- $module.Result.rc = 0
- $module.Result.pid = $command_result.rc
-}
-
-$module.Result.start = $start_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
-$module.Result.end = $end_datetime.ToString("yyyy-MM-dd hh:mm:ss.ffffff")
-$module.Result.delta = $($end_datetime - $start_datetime).ToString("h\:mm\:ss\.ffffff")
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_psexec.py b/lib/ansible/modules/windows/win_psexec.py
deleted file mode 100644
index c3fc37e4a6..0000000000
--- a/lib/ansible/modules/windows/win_psexec.py
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_psexec
-version_added: '2.3'
-short_description: Runs commands (remotely) as another (privileged) user
-description:
-- Run commands (remotely) through the PsExec service.
-- Run commands as another (domain) user (with elevated privileges).
-requirements:
-- Microsoft PsExec
-options:
- command:
- description:
- - The command line to run through PsExec (limited to 260 characters).
- type: str
- required: yes
- executable:
- description:
- - The location of the PsExec utility (in case it is not located in your PATH).
- type: path
- default: psexec.exe
- hostnames:
- description:
- - The hostnames to run the command.
- - If not provided, the command is run locally.
- type: list
- username:
- description:
- - The (remote) user to run the command as.
- - If not provided, the current user is used.
- type: str
- password:
- description:
- - The password for the (remote) user to run the command as.
- - This is mandatory in order authenticate yourself.
- type: str
- chdir:
- description:
- - Run the command from this (remote) directory.
- type: path
- nobanner:
- description:
- - Do not display the startup banner and copyright message.
- - This only works for specific versions of the PsExec binary.
- type: bool
- default: no
- version_added: '2.4'
- noprofile:
- description:
- - Run the command without loading the account's profile.
- type: bool
- default: no
- elevated:
- description:
- - Run the command with elevated privileges.
- type: bool
- default: no
- interactive:
- description:
- - Run the program so that it interacts with the desktop on the remote system.
- type: bool
- default: no
- session:
- description:
- - Specifies the session ID to use.
- - This parameter works in conjunction with I(interactive).
- - It has no effect when I(interactive) is set to C(no).
- type: int
- version_added: '2.7'
- limited:
- description:
- - Run the command as limited user (strips the Administrators group and allows only privileges assigned to the Users group).
- type: bool
- default: no
- system:
- description:
- - Run the remote command in the System account.
- type: bool
- default: no
- priority:
- description:
- - Used to run the command at a different priority.
- choices: [ abovenormal, background, belownormal, high, low, realtime ]
- timeout:
- description:
- - The connection timeout in seconds
- type: int
- wait:
- description:
- - Wait for the application to terminate.
- - Only use for non-interactive applications.
- type: bool
- default: yes
-notes:
-- More information related to Microsoft PsExec is available from
- U(https://technet.microsoft.com/en-us/sysinternals/bb897553.aspx)
-seealso:
-- module: psexec
-- module: raw
-- module: win_command
-- module: win_shell
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-EXAMPLES = r'''
-- name: Test the PsExec connection to the local system (target node) with your user
- win_psexec:
- command: whoami.exe
-
-- name: Run regedit.exe locally (on target node) as SYSTEM and interactively
- win_psexec:
- command: regedit.exe
- interactive: yes
- system: yes
-
-- name: Run the setup.exe installer on multiple servers using the Domain Administrator
- win_psexec:
- command: E:\setup.exe /i /IACCEPTEULA
- hostnames:
- - remote_server1
- - remote_server2
- username: DOMAIN\Administrator
- password: some_password
- priority: high
-
-- name: Run PsExec from custom location C:\Program Files\sysinternals\
- win_psexec:
- command: netsh advfirewall set allprofiles state off
- executable: C:\Program Files\sysinternals\psexec.exe
- hostnames: [ remote_server ]
- password: some_password
- priority: low
-'''
-
-RETURN = r'''
-cmd:
- description: The complete command line used by the module, including PsExec call and additional options.
- returned: always
- type: str
- sample: psexec.exe -nobanner \\remote_server -u "DOMAIN\Administrator" -p "some_password" -accepteula E:\setup.exe
-pid:
- description: The PID of the async process created by PsExec.
- returned: when C(wait=False)
- type: int
- sample: 1532
-rc:
- description: The return code for the command.
- returned: always
- type: int
- sample: 0
-stdout:
- description: The standard output from the command.
- returned: always
- type: str
- sample: Success.
-stderr:
- description: The error output from the command.
- returned: always
- type: str
- sample: Error 15 running E:\setup.exe
-'''
diff --git a/lib/ansible/modules/windows/win_psmodule.ps1 b/lib/ansible/modules/windows/win_psmodule.ps1
deleted file mode 100644
index b24178e49f..0000000000
--- a/lib/ansible/modules/windows/win_psmodule.ps1
+++ /dev/null
@@ -1,468 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Wojciech Sciesinski <wojciech[at]sciesinski[dot]net>
-# Copyright: (c) 2017, Daniele Lazzari <lazzari@mailup.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-# win_psmodule (Windows PowerShell modules Additions/Removals/Updates)
-
-$params = Parse-Args -arguments $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
-$required_version = Get-AnsibleParam -obj $params -name "required_version" -type "str"
-$minimum_version = Get-AnsibleParam -obj $params -name "minimum_version" -type "str"
-$maximum_version = Get-AnsibleParam -obj $params -name "maximum_version" -type "str"
-$repo = Get-AnsibleParam -obj $params -name "repository" -type "str"
-$url = Get-AnsibleParam -obj $params -name "url" -type str
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present", "absent", "latest"
-$allow_clobber = Get-AnsibleParam -obj $params -name "allow_clobber" -type "bool" -default $false
-$skip_publisher_check = Get-AnsibleParam -obj $params -name "skip_publisher_check" -type "bool" -default $false
-$allow_prerelease = Get-AnsibleParam -obj $params -name "allow_prerelease" -type "bool" -default $false
-
-$result = @{changed = $false
- output = ""
- nuget_changed = $false
- repository_changed = $false}
-
-Function Install-NugetProvider {
- Param(
- [Bool]$CheckMode
- )
- $PackageProvider = Get-PackageProvider -ListAvailable | Where-Object { ($_.name -eq 'Nuget') -and ($_.version -ge "2.8.5.201") }
- if (-not($PackageProvider)){
- try {
- Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -WhatIf:$CheckMode | out-null
- $result.changed = $true
- $result.nuget_changed = $true
- }
- catch [ System.Exception ] {
- $ErrorMessage = "Problems adding package provider: $($_.Exception.Message)"
- Fail-Json $result $ErrorMessage
- }
- }
-}
-
-Function Install-PrereqModule {
- Param(
- [Switch]$TestInstallationOnly,
- [Bool]$CheckMode
- )
-
- # Those are minimum required versions of modules.
- $PrereqModules = @{
- PackageManagement = '1.1.7'
- PowerShellGet = '1.6.0'
- }
-
- [Bool]$PrereqModulesInstalled = $true
-
- ForEach ( $Name in $PrereqModules.Keys ) {
-
- $ExistingPrereqModule = Get-Module -ListAvailable | Where-Object { ($_.name -eq $Name) -and ($_.version -ge $PrereqModules[$Name]) }
-
- if ( -not $ExistingPrereqModule ) {
- if ( $TestInstallationOnly ) {
- $PrereqModulesInstalled = $false
- }
- else {
- try {
- $install_params = @{
- Name = $Name
- MinimumVersion = $PrereqModules[$Name]
- Force = $true
- WhatIf = $CheckMode
- }
- if ((Get-Command -Name Install-Module).Parameters.ContainsKey('SkipPublisherCheck')) {
- $install_params.SkipPublisherCheck = $true
- }
-
- Install-Module @install_params > $null
-
- if ( $Name -eq 'PowerShellGet' ) {
- # An order has to be reverted due to dependency
- Remove-Module -Name PowerShellGet, PackageManagement -Force
- Import-Module -Name PowerShellGet, PackageManagement -Force
- }
-
- $result.changed = $true
- }
- catch [ System.Exception ] {
- $ErrorMessage = "Problems adding a prerequisite module $Name $($_.Exception.Message)"
- Fail-Json $result $ErrorMessage
- }
- }
- }
- }
-
- if ( $TestInstallationOnly ) {
- $PrereqModulesInstalled
- }
-}
-
-Function Get-PsModule {
- Param(
- [Parameter(Mandatory=$true)]
- [String]$Name,
- [String]$RequiredVersion,
- [String]$MinimumVersion,
- [String]$MaximumVersion
- )
-
- $ExistingModule = @{
- Exists = $false
- Version = ""
- }
-
- $ExistingModules = Get-Module -Listavailable | Where-Object {($_.name -eq $Name)}
- $ExistingModulesCount = $($ExistingModules | Measure-Object).Count
-
- if ( $ExistingModulesCount -gt 0 ) {
-
- $ExistingModules | Add-Member -MemberType ScriptProperty -Name FullVersion -Value { if ( $null -ne ( $this.PrivateData ) ) { [String]"$($this.Version)-$(($this | Select-Object -ExpandProperty PrivateData).PSData.Prerelease)".TrimEnd('-') } else { [String]"$($this.Version)" } }
-
- if ( -not ($RequiredVersion -or
- $MinimumVersion -or
- $MaximumVersion) ) {
-
- $ReturnedModule = $ExistingModules | Select-Object -First 1
- }
- elseif ( $RequiredVersion ) {
- $ReturnedModule = $ExistingModules | Where-Object -FilterScript { $_.FullVersion -eq $RequiredVersion }
- }
- elseif ( $MinimumVersion -and $MaximumVersion ) {
- $ReturnedModule = $ExistingModules | Where-Object -FilterScript { $MinimumVersion -le $_.Version -and $MaximumVersion -ge $_.Version } | Select-Object -First 1
- }
- elseif ( $MinimumVersion ) {
- $ReturnedModule = $ExistingModules | Where-Object -FilterScript { $MinimumVersion -le $_.Version } | Select-Object -First 1
- }
- elseif ( $MaximumVersion ) {
- $ReturnedModule = $ExistingModules | Where-Object -FilterScript { $MaximumVersion -ge $_.Version } | Select-Object -First 1
- }
- }
-
- $ReturnedModuleCount = ($ReturnedModule | Measure-Object).Count
-
- if ( $ReturnedModuleCount -eq 1 ) {
- $ExistingModule.Exists = $true
- $ExistingModule.Version = $ReturnedModule.FullVersion
- }
-
- $ExistingModule
-}
-
-Function Add-DefinedParameter {
- Param (
- [Parameter(Mandatory=$true)]
- [Hashtable]$Hashtable,
- [Parameter(Mandatory=$true)]
- [String[]]$ParametersNames
- )
-
- ForEach ($ParameterName in $ParametersNames) {
- $ParameterVariable = Get-Variable -Name $ParameterName -ErrorAction Ignore
- if ( $ParameterVariable.Value -and $Hashtable.Keys -notcontains $ParameterName ){
- $Hashtable.Add($ParameterName,$ParameterVariable.Value)
- }
- }
-
- $Hashtable
-}
-
-Function Install-PsModule {
- Param(
- [Parameter(Mandatory=$true)]
- [String]$Name,
- [String]$RequiredVersion,
- [String]$MinimumVersion,
- [String]$MaximumVersion,
- [String]$Repository,
- [Bool]$AllowClobber,
- [Bool]$SkipPublisherCheck,
- [Bool]$AllowPrerelease,
- [Bool]$CheckMode
- )
-
- $ExistingModuleBefore = Get-PsModule -Name $Name -RequiredVersion $RequiredVersion -MinimumVersion $MinimumVersion -MaximumVersion $MaximumVersion
-
- if ( -not $ExistingModuleBefore.Exists ) {
- try {
- # Install NuGet provider if needed.
- Install-NugetProvider -CheckMode $CheckMode
-
- $ht = @{
- Name = $Name
- WhatIf = $CheckMode
- Force = $true
- }
-
- [String[]]$ParametersNames = @("RequiredVersion","MinimumVersion","MaximumVersion","AllowPrerelease","AllowClobber","SkipPublisherCheck","Repository")
-
- $ht = Add-DefinedParameter -Hashtable $ht -ParametersNames $ParametersNames
-
- Install-Module @ht -ErrorVariable ErrorDetails | out-null
-
- $result.changed = $true
- $result.output = "Module $($Name) installed"
- }
- catch [ System.Exception ] {
- $ErrorMessage = "Problems installing $($Name) module: $($_.Exception.Message)"
- Fail-Json $result $ErrorMessage
- }
- }
- else {
- $result.output = "Module $($Name) already present"
- }
-}
-
-Function Remove-PsModule {
- Param(
- [Parameter(Mandatory=$true)]
- [String]$Name,
- [String]$RequiredVersion,
- [String]$MinimumVersion,
- [String]$MaximumVersion,
- [Bool]$CheckMode
- )
- # If module is present, uninstalls it.
- if (Get-Module -Listavailable | Where-Object {$_.name -eq $Name}) {
- try {
- $ht = @{
- Name = $Name
- Confirm = $false
- Force = $true
- }
-
- $ExistingModuleBefore = Get-PsModule -Name $Name -RequiredVersion $RequiredVersion -MinimumVersion $MinimumVersion -MaximumVersion $MaximumVersion
-
- [String[]]$ParametersNames = @("RequiredVersion","MinimumVersion","MaximumVersion")
-
- $ht = Add-DefinedParameter -Hashtable $ht -ParametersNames $ParametersNames
-
- if ( -not ( $RequiredVersion -or $MinimumVersion -or $MaximumVersion ) ) {
- $ht.Add("AllVersions", $true)
- }
-
- if ( $ExistingModuleBefore.Exists) {
- # The Force parameter overwrite the WhatIf parameter
- if ( -not $CheckMode ) {
- Uninstall-Module @ht -ErrorVariable ErrorDetails | out-null
- }
- $result.changed = $true
- $result.output = "Module $($Name) removed"
- }
- }
- catch [ System.Exception ] {
- $ErrorMessage = "Problems uninstalling $($Name) module: $($_.Exception.Message)"
- Fail-Json $result $ErrorMessage
- }
- }
- else {
- $result.output = "Module $($Name) removed"
- }
-}
-
-Function Find-LatestPsModule {
- Param(
- [Parameter(Mandatory=$true)]
- [String]$Name,
- [String]$Repository,
- [Bool]$AllowPrerelease,
- [Bool]$CheckMode
- )
-
- try {
- $ht = @{
- Name = $Name
- }
-
- [String[]]$ParametersNames = @("AllowPrerelease","Repository")
-
- $ht = Add-DefinedParameter -Hashtable $ht -ParametersNames $ParametersNames
-
- $LatestModule = Find-Module @ht
- $LatestModuleVersion = $LatestModule.Version
- }
- catch [ System.Exception ] {
- $ErrorMessage = "Cant find the module $($Name): $($_.Exception.Message)"
- Fail-Json $result $ErrorMessage
- }
-
- $LatestModuleVersion
-}
-
-Function Install-Repository {
- Param(
- [Parameter(Mandatory=$true)]
- [string]$Name,
- [Parameter(Mandatory=$true)]
- [string]$Url,
- [bool]$CheckMode
- )
- Add-DeprecationWarning -obj $result -message "Adding a repo with this module is deprecated, the repository parameter should only be used to select a repo. Use win_psrepository to manage repos" -version 2.12
- # Install NuGet provider if needed.
- Install-NugetProvider -CheckMode $CheckMode
-
- $Repos = (Get-PSRepository).SourceLocation
-
- # If repository isn't already present, try to register it as trusted.
- if ($Repos -notcontains $Url){
- try {
- if ( -not ($CheckMode) ) {
- Register-PSRepository -Name $Name -SourceLocation $Url -InstallationPolicy Trusted -ErrorAction Stop
- }
- $result.changed = $true
- $result.repository_changed = $true
- }
- catch {
- $ErrorMessage = "Problems registering $($Name) repository: $($_.Exception.Message)"
- Fail-Json $result $ErrorMessage
- }
- }
-}
-
-Function Remove-Repository{
- Param(
- [Parameter(Mandatory=$true)]
- [string]$Name,
- [bool]$CheckMode
- )
- Add-DeprecationWarning -obj $result -message "Removing a repo with this module is deprecated, use win_psrepository to manage repos" -version 2.12
-
- $Repo = (Get-PSRepository).Name
-
- # Try to remove the repository
- if ($Repo -contains $Name){
- try {
- if ( -not ($CheckMode) ) {
- Unregister-PSRepository -Name $Name -ErrorAction Stop
- }
- $result.changed = $true
- $result.repository_changed = $true
- }
- catch [ System.Exception ] {
- $ErrorMessage = "Problems unregistering $($Name)repository: $($_.Exception.Message)"
- Fail-Json $result $ErrorMessage
- }
- }
-}
-
-# Check PowerShell version, fail if < 5.0 and required modules are not installed
-$PsVersion = $PSVersionTable.PSVersion
-if ($PsVersion.Major -lt 5 ) {
- $PrereqModulesInstalled = Install-PrereqModule -TestInstallationOnly
- if ( -not $PrereqModulesInstalled ) {
- $ErrorMessage = "Modules PowerShellGet and PackageManagement in versions 1.6.0 and 1.1.7 respectively have to be installed before using the win_psmodule."
- Fail-Json $result $ErrorMessage
- }
-}
-
-if ( $required_version -and ( $minimum_version -or $maximum_version ) ) {
- $ErrorMessage = "Parameters required_version and minimum/maximum_version are mutually exclusive."
- Fail-Json $result $ErrorMessage
-}
-
-if ( $allow_prerelease -and ( $minimum_version -or $maximum_version ) ) {
- $ErrorMessage = "Parameters minimum_version, maximum_version can't be used with the parameter allow_prerelease."
- Fail-Json $result $ErrorMessage
-}
-
-if ( $allow_prerelease -and $state -eq "absent" ) {
- $ErrorMessage = "The parameter allow_prerelease can't be used with state set to 'absent'."
- Fail-Json $result $ErrorMessage
-}
-
-if ( ($state -eq "latest") -and
- ( $required_version -or $minimum_version -or $maximum_version ) ) {
- $ErrorMessage = "When the parameter state is equal 'latest' you can use any of required_version, minimum_version, maximum_version."
- Fail-Json $result $ErrorMessage
-}
-
-if ( $repo -and (-not $url) ) {
- $RepositoryExists = Get-PSRepository -Name $repo -ErrorAction Ignore
- if ( $null -eq $RepositoryExists) {
- $ErrorMessage = "The repository $repo doesn't exist."
- Fail-Json $result $ErrorMessage
- }
-
-}
-
-if ( ($allow_clobber -or $allow_prerelease -or $skip_publisher_check -or
- $required_version -or $minimum_version -or $maximum_version) ) {
- # Update the PowerShellGet and PackageManagement modules.
- # It's required to support AllowClobber, AllowPrerelease parameters.
- Install-PrereqModule -CheckMode $check_mode
-}
-
-Import-Module -Name PackageManagement, PowerShellGet
-
-if ($state -eq "present") {
- if (($repo) -and ($url)) {
- Install-Repository -Name $repo -Url $url -CheckMode $check_mode
- }
- else {
- $ErrorMessage = "Repository Name and Url are mandatory if you want to add a new repository"
- }
-
- if ($name) {
- $ht = @{
- Name = $name
- RequiredVersion = $required_version
- MinimumVersion = $minimum_version
- MaximumVersion = $maximum_version
- Repository = $repo
- AllowClobber = $allow_clobber
- SkipPublisherCheck = $skip_publisher_check
- AllowPrerelease = $allow_prerelease
- CheckMode = $check_mode
- }
- Install-PsModule @ht
- }
-}
-elseif ($state -eq "absent") {
- if ($repo) {
- Remove-Repository -Name $repo -CheckMode $check_mode
- }
-
- if ($name) {
- $ht = @{
- Name = $Name
- CheckMode = $check_mode
- RequiredVersion = $required_version
- MinimumVersion = $minimum_version
- MaximumVersion = $maximum_version
- }
- Remove-PsModule @ht
- }
-}
-elseif ( $state -eq "latest") {
-
- $ht = @{
- Name = $Name
- AllowPrerelease = $allow_prerelease
- Repository = $repo
- CheckMode = $check_mode
- }
-
- $LatestVersion = Find-LatestPsModule @ht
-
- $ExistingModule = Get-PsModule $Name
-
- if ( $LatestVersion.Version -ne $ExistingModule.Version ) {
-
- $ht = @{
- Name = $Name
- RequiredVersion = $LatestVersion
- Repository = $repo
- AllowClobber = $allow_clobber
- SkipPublisherCheck = $skip_publisher_check
- AllowPrerelease = $allow_prerelease
- CheckMode = $check_mode
- }
- Install-PsModule @ht
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_psmodule.py b/lib/ansible/modules/windows/win_psmodule.py
deleted file mode 100644
index d779e99c9c..0000000000
--- a/lib/ansible/modules/windows/win_psmodule.py
+++ /dev/null
@@ -1,155 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Wojciech Sciesinski <wojciech[at]sciesinski[dot]net>
-# Copyright: (c) 2017, Daniele Lazzari <lazzari@mailup.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_psmodule
-version_added: "2.4"
-short_description: Adds or removes a Windows PowerShell module
-description:
- - This module helps to install Windows PowerShell modules and register custom modules repository on Windows-based systems.
-options:
- name:
- description:
- - Name of the Windows PowerShell module that has to be installed.
- type: str
- required: yes
- state:
- description:
- - If C(present) a new module is installed.
- - If C(absent) a module is removed.
- - If C(latest) a module is updated to the newest version. This option was added in version 2.8.
- type: str
- choices: [ absent, latest, present ]
- default: present
- required_version:
- description:
- - The exact version of the PowerShell module that has to be installed.
- type: str
- version_added: "2.8"
- minimum_version:
- description:
- - The minimum version of the PowerShell module that has to be installed.
- type: str
- version_added: "2.8"
- maximum_version:
- description:
- - The maximum version of the PowerShell module that has to be installed.
- type: str
- version_added: "2.8"
- allow_clobber:
- description:
- - If C(yes) allows install modules that contains commands those have the same names as commands that already exists.
- type: bool
- default: no
- skip_publisher_check:
- description:
- - If C(yes), allows you to install a different version of a module that already exists on your computer in the case when a different one
- is not digitally signed by a trusted publisher and the newest existing module is digitally signed by a trusted publisher.
- type: bool
- default: no
- version_added: "2.8"
- allow_prerelease:
- description:
- - If C(yes) installs modules marked as prereleases.
- - It doesn't work with the parameters C(minimum_version) and/or C(maximum_version).
- - It doesn't work with the C(state) set to absent.
- type: bool
- default: no
- version_added: "2.8"
- repository:
- description:
- - Name of the custom repository to use.
- type: str
- url:
- description:
- - URL of the custom repository to register.
- - This option is deprecated and will be removed in Ansible 2.12. Use the
- M(win_psrepository) module instead.
- type: str
-notes:
- - PowerShell modules needed
- - PowerShellGet >= 1.6.0
- - PackageManagement >= 1.1.7
- - PowerShell package provider needed
- - NuGet >= 2.8.5.201
- - On PowerShell 5.x required modules and a package provider will be updated under the first run of the win_psmodule module.
- - On PowerShell 3.x and 4.x you have to install them before using the win_psmodule.
-seealso:
-- module: win_psrepository
-author:
-- Wojciech Sciesinski (@it-praktyk)
-- Daniele Lazzari (@dlazz)
-'''
-
-EXAMPLES = r'''
----
-- name: Add a PowerShell module
- win_psmodule:
- name: PowerShellModule
- state: present
-
-- name: Add an exact version of PowerShell module
- win_psmodule:
- name: PowerShellModule
- required_version: "4.0.2"
- state: present
-
-- name: Install or update an existing PowerShell module to the newest version
- win_psmodule:
- name: PowerShellModule
- state: latest
-
-- name: Install newer version of built-in Windows module
- win_psmodule:
- name: Pester
- skip_publisher_check: yes
- state: present
-
-- name: Add a PowerShell module and register a repository
- win_psmodule:
- name: MyCustomModule
- repository: MyRepository
- state: present
-
-- name: Add a PowerShell module from a specific repository
- win_psmodule:
- name: PowerShellModule
- repository: MyRepository
- state: present
-
-- name: Remove a PowerShell module
- win_psmodule:
- name: PowerShellModule
- state: absent
-'''
-
-RETURN = r'''
----
-output:
- description: A message describing the task result.
- returned: always
- sample: "Module PowerShellCookbook installed"
- type: str
-nuget_changed:
- description: True when Nuget package provider is installed.
- returned: always
- type: bool
- sample: true
-repository_changed:
- description: True when a custom repository is installed or removed.
- returned: always
- type: bool
- sample: true
-'''
diff --git a/lib/ansible/modules/windows/win_psrepository.ps1 b/lib/ansible/modules/windows/win_psrepository.ps1
deleted file mode 100644
index da637f02eb..0000000000
--- a/lib/ansible/modules/windows/win_psrepository.ps1
+++ /dev/null
@@ -1,68 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Wojciech Sciesinski <wojciech[at]sciesinski[dot]net>
-# Copyright: (c) 2017, Daniele Lazzari <lazzari@mailup.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-# win_psrepository (Windows PowerShell repositories Additions/Removals/Updates)
-
-$params = Parse-Args -arguments $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
-$source = Get-AnsibleParam -obj $params -name "source" -type "str"
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "present", "absent"
-$installationpolicy = Get-AnsibleParam -obj $params -name "installation_policy" -type "str" -validateset "trusted", "untrusted"
-
-$result = @{"changed" = $false}
-
-Function Update-NuGetPackageProvider {
- $PackageProvider = Get-PackageProvider -ListAvailable | Where-Object { ($_.name -eq 'Nuget') -and ($_.version -ge "2.8.5.201") }
- if ($null -eq $PackageProvider) {
- Find-PackageProvider -Name Nuget -ForceBootstrap -IncludeDependencies -Force | Out-Null
- }
-}
-
-$Repo = Get-PSRepository -Name $name -ErrorAction Ignore
-if ($state -eq "present") {
- if ($null -eq $Repo) {
- if ($null -eq $installationpolicy) {
- $installationpolicy = "trusted"
- }
- if (-not $check_mode) {
- Update-NuGetPackageProvider
- Register-PSRepository -Name $name -SourceLocation $source -InstallationPolicy $installationpolicy
- }
- $result.changed = $true
- }
- else {
- $changed_properties = @{}
-
- if ($Repo.SourceLocation -ne $source) {
- $changed_properties.SourceLocation = $source
- }
-
- if ($null -ne $installationpolicy -and $Repo.InstallationPolicy -ne $installationpolicy) {
- $changed_properties.InstallationPolicy = $installationpolicy
- }
-
- if ($changed_properties.Count -gt 0) {
- if (-not $check_mode) {
- Update-NuGetPackageProvider
- Set-PSRepository -Name $name @changed_properties
- }
- $result.changed = $true
- }
- }
-}
-elseif ($state -eq "absent" -and $null -ne $Repo) {
- if (-not $check_mode) {
- Update-NuGetPackageProvider
- Unregister-PSRepository -Name $name
- }
- $result.changed = $true
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_psrepository.py b/lib/ansible/modules/windows/win_psrepository.py
deleted file mode 100644
index a4faa1c6cf..0000000000
--- a/lib/ansible/modules/windows/win_psrepository.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Wojciech Sciesinski <wojciech[at]sciesinski[dot]net>
-# Copyright: (c) 2017, Daniele Lazzari <lazzari@mailup.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_psrepository
-version_added: "2.8"
-short_description: Adds, removes or updates a Windows PowerShell repository.
-description:
- - This module helps to add, remove and update Windows PowerShell repository on Windows-based systems.
-options:
- name:
- description:
- - Name of the repository to work with.
- type: str
- required: yes
- source:
- description:
- - Specifies the URI for discovering and installing modules from this repository.
- - A URI can be a NuGet server feed (most common situation), HTTP, HTTPS, FTP or file location.
- type: str
- state:
- description:
- - If C(present) a new repository is added or updated.
- - If C(absent) a repository is removed.
- type: str
- choices: [ absent, present ]
- default: present
- installation_policy:
- description:
- - Sets the C(InstallationPolicy) of a repository.
- - Will default to C(trusted) when creating a new repository.
- type: str
- choices: [ trusted, untrusted ]
-notes:
- - PowerShell modules needed
- - PowerShellGet >= 1.6.0
- - PackageManagement >= 1.1.7
- - PowerShell package provider needed
- - NuGet >= 2.8.5.201
- - See the examples on how to update the NuGet package provider.
- - You can not use C(win_psrepository) to re-register (add) removed PSGallery, use the command C(Register-PSRepository -Default) instead.
-seealso:
-- module: win_psmodule
-author:
-- Wojciech Sciesinski (@it-praktyk)
-'''
-
-EXAMPLES = '''
----
-- name: Ensure the required NuGet package provider version is installed
- win_shell: Find-PackageProvider -Name Nuget -ForceBootstrap -IncludeDependencies -Force
-
-- name: Add a PowerShell module and register a repository
- win_psrepository:
- name: MyRepository
- source: https://myrepo.com
- state: present
-
-- name: Remove a PowerShell repository
- win_psrepository:
- name: MyRepository
- state: absent
-'''
-
-RETURN = '''
-'''
diff --git a/lib/ansible/modules/windows/win_psrepository_info.ps1 b/lib/ansible/modules/windows/win_psrepository_info.ps1
deleted file mode 100644
index 93e3585bef..0000000000
--- a/lib/ansible/modules/windows/win_psrepository_info.ps1
+++ /dev/null
@@ -1,68 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2020, Brian Scholer <@briantist>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.CamelConversion
-#Requires -Module PowerShellGet
-
-$spec = @{
- options = @{
- name = @{ type = 'str' ; default = '*' }
- }
- supports_check_mode = $true
-}
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-function Convert-ObjectToSnakeCase {
- <#
- .SYNOPSIS
- Converts an object with CamelCase properties to a dictionary with snake_case keys.
- Works in the spirit of and depends on the existing CamelConversion module util.
- #>
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
- [OutputType([System.Collections.Specialized.OrderedDictionary])]
- [Object]
- $InputObject ,
-
- [Parameter()]
- [Switch]
- $NoRecurse ,
-
- [Parameter()]
- [Switch]
- $OmitNull
- )
-
- Process {
- $result = [Ordered]@{}
- foreach ($property in $InputObject.PSObject.Properties) {
- $value = $property.Value
- if (-not $NoRecurse -and $value -is [System.Collections.IDictionary]) {
- $value = Convert-DictToSnakeCase -dict $value
- }
- elseif (-not $NoRecurse -and ($value -is [Array] -or $value -is [System.Collections.ArrayList])) {
- $value = Convert-ListToSnakeCase -list $value
- }
- elseif ($null -eq $value) {
- if ($OmitNull) {
- continue
- }
- }
- elseif (-not $NoRecurse -and $value -isnot [System.ValueType] -and $value -isnot [string]) {
- $value = Convert-ObjectToSnakeCase -InputObject $value
- }
-
- $name = Convert-StringToSnakeCase -string $property.Name
- $result[$name] = $value
- }
- $result
- }
-}
-
-$module.Result.repositories = @(Get-PSRepository -Name $module.Params.name | Convert-ObjectToSnakeCase)
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_psrepository_info.py b/lib/ansible/modules/windows/win_psrepository_info.py
deleted file mode 100644
index 1bcbee1bb5..0000000000
--- a/lib/ansible/modules/windows/win_psrepository_info.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2020, Brian Scholer <@briantist>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_psrepository_info
-version_added: '2.10'
-short_description: Gather information about PSRepositories
-description:
- - Gather information about all or a specific PSRepository.
-options:
- name:
- description:
- - The name of the repository to retrieve.
- - Supports any wildcard pattern supported by C(Get-PSRepository).
- - If omitted then all repositories will returned.
- type: str
- default: '*'
-requirements:
- - C(PowerShellGet) module
-seealso:
- - module: win_psrepository
-author:
- - Brian Scholer (@briantist)
-'''
-
-EXAMPLES = r'''
-- name: Get info for a single repository
- win_psrepository_info:
- name: PSGallery
- register: repo_info
-
-- name: Find all repositories that start with 'MyCompany'
- win_psrepository_info:
- name: MyCompany*
-
-- name: Get info for all repositories
- win_psrepository_info:
- register: repo_info
-
-- name: Remove all repositories that don't have a publish_location set
- win_psrepository:
- name: "{{ item }}"
- state: absent
- loop: "{{ repo_info.repositories | rejectattr('publish_location', 'none') | list }}"
-'''
-
-RETURN = r'''
-repositories:
- description:
- - A list of repositories (or an empty list is there are none).
- returned: always
- type: list
- elements: dict
- contains:
- name:
- description:
- - The name of the repository.
- type: str
- sample: PSGallery
- installation_policy:
- description:
- - The installation policy of the repository. The sample values are the only possible values.
- type: str
- sample:
- - Trusted
- - Untrusted
- trusted:
- description:
- - A boolean flag reflecting the value of C(installation_policy) as to whether the repository is trusted.
- type: bool
- package_management_provider:
- description:
- - The name of the package management provider for this repository.
- type: str
- sample: NuGet
- provider_options:
- description:
- - Provider-specific options for this repository.
- type: dict
- source_location:
- description:
- - The location used to find and retrieve modules. This should always have a value.
- type: str
- sample: https://www.powershellgallery.com/api/v2
- publish_location:
- description:
- - The location used to publish modules.
- type: str
- sample: https://www.powershellgallery.com/api/v2/package/
- script_source_location:
- description:
- - The location used to find and retrieve scripts.
- type: str
- sample: https://www.powershellgallery.com/api/v2/items/psscript
- script_publish_location:
- description:
- - The location used to publish scripts.
- type: str
- sample: https://www.powershellgallery.com/api/v2/package/
- registered:
- description:
- - Whether the module is registered. Should always be C(True)
- type: bool
-'''
diff --git a/lib/ansible/modules/windows/win_rabbitmq_plugin.ps1 b/lib/ansible/modules/windows/win_rabbitmq_plugin.ps1
deleted file mode 100644
index 1c79f0c41e..0000000000
--- a/lib/ansible/modules/windows/win_rabbitmq_plugin.ps1
+++ /dev/null
@@ -1,157 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-function Get-EnabledPlugins($rabbitmq_plugins_cmd)
-{
- $list_plugins_cmd = "$rabbitmq_plugins_cmd list -E -m"
- try {
- $enabled_plugins = @(Invoke-Expression "& $list_plugins_cmd" | Where-Object { $_ })
- return ,$enabled_plugins
- }
- catch {
- Fail-Json -obj $result -message "Can't execute `"$($list_plugins_cmd)`": $($_.Exception.Message)"
- }
-}
-
-function Enable-Plugin($rabbitmq_plugins_cmd, $plugin_name)
-{
- $enable_plugin_cmd = "$rabbitmq_plugins_cmd enable $plugin_name"
- try {
- Invoke-Expression "& $enable_plugin_cmd"
- }
- catch {
- Fail-Json -obj $result -message "Can't execute `"$($enable_plugin_cmd)`": $($_.Exception.Message)"
- }
-}
-
-function Disable-Plugin($rabbitmq_plugins_cmd, $plugin_name)
-{
- $enable_plugin_cmd = "$rabbitmq_plugins_cmd disable $plugin_name"
- try {
- Invoke-Expression "& $enable_plugin_cmd"
- }
- catch {
- Fail-Json -obj $result -message "Can't execute `"$($enable_plugin_cmd)`": $($_.Exception.Message)"
- }
-}
-
-function Get-RabbitmqPathFromRegistry
-{
- $reg64Path = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\RabbitMQ"
- $reg32Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\RabbitMQ"
-
- if (Test-Path $reg64Path) {
- $regPath = $reg64Path
- } elseif (Test-Path $reg32Path) {
- $regPath = $reg32Path
- }
-
- if ($regPath) {
- $path = Split-Path -Parent (Get-ItemProperty $regPath "UninstallString").UninstallString
- $version = (Get-ItemProperty $regPath "DisplayVersion").DisplayVersion
- return "$path\rabbitmq_server-$version"
- }
-}
-
-function Get-RabbitmqBinPath($installation_path)
-{
- $result = Join-Path -Path $installation_path -ChildPath 'bin'
- if (Test-Path $result) {
- return $result
- }
-
- $result = Join-Path -Path $installation_path -ChildPath 'sbin'
- if (Test-Path $result) {
- return $result
- }
-}
-
-$ErrorActionPreference = "Stop"
-
-$result = @{
- changed = $false
- enabled = @()
- disabled = @()
-}
-
-$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
-
-$names = Get-AnsibleParam -obj $params -name "names" -type "str" -failifempty $true -aliases "name"
-$new_only = Get-AnsibleParam -obj $params -name "new_only" -type "bool" -default $false
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "enabled" -validateset "enabled","disabled"
-$prefix = Get-AnsibleParam -obj $params -name "prefix" -type "str"
-
-if ($diff_support) {
- $result.diff = @{}
- $result.diff.prepared = ""
-}
-
-$plugins = $names.Split(",")
-
-if ($prefix) {
- $rabbitmq_bin_path = Get-RabbitmqBinPath -installation_path $prefix
- if (-not $rabbitmq_bin_path) {
- Fail-Json -obj $result -message "No binary folder in prefix `"$($prefix)`""
- }
-} else {
- $rabbitmq_reg_path = Get-RabbitmqPathFromRegistry
- if ($rabbitmq_reg_path) {
- $rabbitmq_bin_path = Get-RabbitmqBinPath -installation_path $rabbitmq_reg_path
- }
-}
-
-if ($rabbitmq_bin_path) {
- $rabbitmq_plugins_cmd = "'$(Join-Path -Path $rabbitmq_bin_path -ChildPath "rabbitmq-plugins")'"
-} else {
- $rabbitmq_plugins_cmd = "rabbitmq-plugins"
-}
-
-$enabled_plugins = Get-EnabledPlugins -rabbitmq_plugins_cmd $rabbitmq_plugins_cmd
-
-if ($state -eq "enabled") {
- $plugins_to_enable = $plugins | Where-Object {-not ($enabled_plugins -contains $_)}
- foreach ($plugin in $plugins_to_enable) {
- if (-not $check_mode) {
- Enable-Plugin -rabbitmq_plugins_cmd $rabbitmq_plugins_cmd -plugin_name $plugin
- }
- if ($diff_support) {
- $result.diff.prepared += "+[$plugin]`n"
- }
- $result.enabled += $plugin
- $result.changed = $true
- }
-
- if (-not $new_only) {
- $plugins_to_disable = $enabled_plugins | Where-Object {-not ($plugins -contains $_)}
- foreach ($plugin in $plugins_to_disable) {
- if (-not $check_mode) {
- Disable-Plugin -rabbitmq_plugins_cmd $rabbitmq_plugins_cmd -plugin_name $plugin
- }
- if ($diff_support) {
- $result.diff.prepared += "-[$plugin]`n"
- }
- $result.disabled += $plugin
- $result.changed = $true
- }
- }
-} else {
- $plugins_to_disable = $enabled_plugins | Where-Object {$plugins -contains $_}
- foreach ($plugin in $plugins_to_disable) {
- if (-not $check_mode) {
- Disable-Plugin -rabbitmq_plugins_cmd $rabbitmq_plugins_cmd -plugin_name $plugin
- }
- if ($diff_support) {
- $result.diff.prepared += "-[$plugin]`n"
- }
- $result.disabled += $plugin
- $result.changed = $true
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_rabbitmq_plugin.py b/lib/ansible/modules/windows/win_rabbitmq_plugin.py
deleted file mode 100644
index 783559c595..0000000000
--- a/lib/ansible/modules/windows/win_rabbitmq_plugin.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_rabbitmq_plugin
-short_description: Manage RabbitMQ plugins
-description:
- - Manage RabbitMQ plugins.
-version_added: "2.4"
-options:
- names:
- description:
- - Comma-separated list of plugin names.
- type: str
- required: yes
- aliases: [ name ]
- new_only:
- description:
- - Only enable missing plugins.
- - Does not disable plugins that are not in the names list.
- type: bool
- default: no
- state:
- description:
- - Specify if plugins are to be enabled or disabled.
- type: str
- choices: [ disabled, enabled ]
- default: enabled
- prefix:
- description:
- - Specify a custom install prefix to a Rabbit.
- type: str
-author:
- - Artem Zinenko (@ar7z1)
-'''
-
-EXAMPLES = r'''
-- name: Enables the rabbitmq_management plugin
- win_rabbitmq_plugin:
- names: rabbitmq_management
- state: enabled
-'''
-
-RETURN = r'''
-enabled:
- description: List of plugins enabled during task run.
- returned: always
- type: list
- sample: ["rabbitmq_management"]
-disabled:
- description: List of plugins disabled during task run.
- returned: always
- type: list
- sample: ["rabbitmq_management"]
-'''
diff --git a/lib/ansible/modules/windows/win_rds_cap.ps1 b/lib/ansible/modules/windows/win_rds_cap.ps1
deleted file mode 100644
index 1bc61ce475..0000000000
--- a/lib/ansible/modules/windows/win_rds_cap.ps1
+++ /dev/null
@@ -1,357 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.SID
-
-$ErrorActionPreference = "Stop"
-
-# List of authentication methods as string. Used for parameter validation and conversion to integer flag, so order is important!
-$auth_methods_set = @("none", "password", "smartcard", "both")
-# List of session timeout actions as string. Used for parameter validation and conversion to integer flag, so order is important!
-$session_timeout_actions_set = @("disconnect", "reauth")
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -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 "absent","present","enabled","disabled"
-$auth_method = Get-AnsibleParam -obj $params -name "auth_method" -type "str" -validateset $auth_methods_set
-$order = Get-AnsibleParam -obj $params -name "order" -type "int"
-$session_timeout = Get-AnsibleParam -obj $params -name "session_timeout" -type "int"
-$session_timeout_action = Get-AnsibleParam -obj $params -name "session_timeout_action" -type "str" -default "disconnect" -validateset $session_timeout_actions_set
-$idle_timeout = Get-AnsibleParam -obj $params -name "idle_timeout" -type "int"
-$allow_only_sdrts_servers = Get-AnsibleParam -obj $params -name "allow_only_sdrts_servers" -type "bool"
-$user_groups = Get-AnsibleParam -obj $params -name "user_groups" -type "list"
-$computer_groups = Get-AnsibleParam -obj $params -name "computer_groups" -type "list"
-
-# Device redirections
-$redirect_clipboard = Get-AnsibleParam -obj $params -name "redirect_clipboard" -type "bool"
-$redirect_drives = Get-AnsibleParam -obj $params -name "redirect_drives" -type "bool"
-$redirect_printers = Get-AnsibleParam -obj $params -name "redirect_printers" -type "bool"
-$redirect_serial = Get-AnsibleParam -obj $params -name "redirect_serial" -type "bool"
-$redirect_pnp = Get-AnsibleParam -obj $params -name "redirect_pnp" -type "bool"
-
-
-function Get-CAP([string] $name) {
- $cap_path = "RDS:\GatewayServer\CAP\$name"
- $cap = @{
- Name = $name
- }
-
- # Fetch CAP properties
- Get-ChildItem -Path $cap_path | ForEach-Object { $cap.Add($_.Name,$_.CurrentValue) }
- # Convert boolean values
- $cap.Enabled = $cap.Status -eq 1
- $cap.Remove("Status")
- $cap.AllowOnlySDRTSServers = $cap.AllowOnlySDRTSServers -eq 1
-
- # Convert multiple choices values
- $cap.AuthMethod = $auth_methods_set[$cap.AuthMethod]
- $cap.SessionTimeoutAction = $session_timeout_actions_set[$cap.SessionTimeoutAction]
-
- # Fetch CAP device redirection settings
- $cap.DeviceRedirection = @{}
- Get-ChildItem -Path "$cap_path\DeviceRedirection" | ForEach-Object { $cap.DeviceRedirection.Add($_.Name, ($_.CurrentValue -eq 1)) }
-
- # Fetch CAP user and computer groups in Down-Level Logon format
- $cap.UserGroups = @(
- Get-ChildItem -Path "$cap_path\UserGroups" |
- Select-Object -ExpandProperty Name |
- ForEach-Object { Convert-FromSID -sid (Convert-ToSID -account_name $_) }
- )
- $cap.ComputerGroups = @(
- Get-ChildItem -Path "$cap_path\ComputerGroups" |
- Select-Object -ExpandProperty Name |
- ForEach-Object { Convert-FromSID -sid (Convert-ToSID -account_name $_) }
- )
-
- return $cap
-}
-
-function Set-CAPPropertyValue {
- [CmdletBinding(SupportsShouldProcess=$true)]
- param (
- [Parameter(Mandatory=$true)]
- [string] $name,
- [Parameter(Mandatory=$true)]
- [string] $property,
- [Parameter(Mandatory=$true)]
- $value,
- [Parameter()]
- $resultobj = @{}
- )
-
- $cap_path = "RDS:\GatewayServer\CAP\$name"
-
- try {
- Set-Item -Path "$cap_path\$property" -Value $value -ErrorAction Stop
- } catch {
- Fail-Json -obj $resultobj -message "Failed to set property $property of CAP ${name}: $($_.Exception.Message)"
- }
-}
-
-$result = @{
- changed = $false
-}
-$diff_text = $null
-
-# Validate CAP name
-if ($name -match "[*/\\;:?`"<>|\t]+") {
- Fail-Json -obj $result -message "Invalid character in CAP name."
-}
-
-# Validate user groups
-if ($null -ne $user_groups) {
- if ($user_groups.Count -lt 1) {
- Fail-Json -obj $result -message "Parameter 'user_groups' cannot be an empty list."
- }
-
- $user_groups = $user_groups | ForEach-Object {
- $group = $_
- # Test that the group is resolvable on the local machine
- $sid = Convert-ToSID -account_name $group
- if (!$sid) {
- Fail-Json -obj $result -message "$group is not a valid user group on the host machine or domain"
- }
-
- # Return the normalized group name in Down-Level Logon format
- Convert-FromSID -sid $sid
- }
- $user_groups = @($user_groups)
-}
-
-# Validate computer groups
-if ($null -ne $computer_groups) {
- $computer_groups = $computer_groups | ForEach-Object {
- $group = $_
- # Test that the group is resolvable on the local machine
- $sid = Convert-ToSID -account_name $group
- if (!$sid) {
- Fail-Json -obj $result -message "$group is not a valid computer group on the host machine or domain"
- }
-
- # Return the normalized group name in Down-Level Logon format
- Convert-FromSID -sid $sid
- }
- $computer_groups = @($computer_groups)
-}
-
-# Validate order parameter
-if ($null -ne $order -and $order -lt 1) {
- Fail-Json -obj $result -message "Parameter 'order' must be a strictly positive integer."
-}
-
-# Ensure RemoteDesktopServices module is loaded
-if ($null -eq (Get-Module -Name RemoteDesktopServices -ErrorAction SilentlyContinue)) {
- Import-Module -Name RemoteDesktopServices
-}
-
-# Check if a CAP with the given name already exists
-$cap_exist = Test-Path -Path "RDS:\GatewayServer\CAP\$name"
-
-if ($state -eq 'absent') {
- if ($cap_exist) {
- Remove-Item -Path "RDS:\GatewayServer\CAP\$name" -Recurse -WhatIf:$check_mode
- $diff_text += "-[$name]"
- $result.changed = $true
- }
-} else {
- $diff_text_added_prefix = ''
- if (-not $cap_exist) {
- if ($null -eq $user_groups) {
- Fail-Json -obj $result -message "User groups must be defined to create a new CAP."
- }
-
- # Auth method is required when creating a new CAP. Set it to password by default.
- if ($null -eq $auth_method) {
- $auth_method = "password"
- }
-
- # Create a new CAP
- if (-not $check_mode) {
- $CapArgs = @{
- Name = $name
- UserGroupNames = $user_groups -join ';'
- }
- $return = Invoke-CimMethod -Namespace Root\CIMV2\TerminalServices -ClassName Win32_TSGatewayConnectionAuthorizationPolicy -MethodName Create -Arguments $CapArgs
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to create CAP $name (code: $($return.ReturnValue))"
- }
- }
-
- $cap_exist = -not $check_mode
-
- $diff_text_added_prefix = '+'
- $result.changed = $true
- }
-
- $diff_text += "$diff_text_added_prefix[$name]`n"
-
- # We cannot configure a CAP that was created above in check mode as it won't actually exist
- if($cap_exist) {
- $cap = Get-CAP -Name $name
- $wmi_cap = Get-CimInstance -ClassName Win32_TSGatewayConnectionAuthorizationPolicy -Namespace Root\CIMv2\TerminalServices -Filter "name='$($name)'"
-
- if ($state -in @('disabled', 'enabled')) {
- $cap_enabled = $state -ne 'disabled'
- if ($cap.Enabled -ne $cap_enabled) {
- $diff_text += "-State = $(@('disabled', 'enabled')[[int]$cap.Enabled])`n+State = $state`n"
- Set-CAPPropertyValue -Name $name -Property Status -Value ([int]$cap_enabled) -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
- }
-
- if ($null -ne $auth_method -and $auth_method -ne $cap.AuthMethod) {
- $diff_text += "-AuthMethod = $($cap.AuthMethod)`n+AuthMethod = $auth_method`n"
- Set-CAPPropertyValue -Name $name -Property AuthMethod -Value ([array]::IndexOf($auth_methods_set, $auth_method)) -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $order -and $order -ne $cap.EvaluationOrder) {
- # Order cannot be greater than the total number of existing CAPs (InvalidArgument exception)
- $cap_count = (Get-ChildItem -Path "RDS:\GatewayServer\CAP").Count
- if($order -gt $cap_count) {
- Add-Warning -obj $result -message "Given value '$order' for parameter 'order' is greater than the number of existing CAPs. The actual order will be capped to '$cap_count'."
- $order = $cap_count
- }
-
- $diff_text += "-Order = $($cap.EvaluationOrder)`n+Order = $order`n"
- Set-CAPPropertyValue -Name $name -Property EvaluationOrder -Value $order -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $session_timeout -and ($session_timeout -ne $cap.SessionTimeout -or $session_timeout_action -ne $cap.SessionTimeoutAction)) {
- try {
- Set-Item -Path "RDS:\GatewayServer\CAP\$name\SessionTimeout" `
- -Value $session_timeout `
- -SessionTimeoutAction ([array]::IndexOf($session_timeout_actions_set, $session_timeout_action)) `
- -ErrorAction Stop `
- -WhatIf:$check_mode
- } catch {
- Fail-Json -obj $result -message "Failed to set property ComputerGroupType of RAP ${name}: $($_.Exception.Message)"
- }
-
- $diff_text += "-SessionTimeoutAction = $($cap.SessionTimeoutAction)`n+SessionTimeoutAction = $session_timeout_action`n"
- $diff_text += "-SessionTimeout = $($cap.SessionTimeout)`n+SessionTimeout = $session_timeout`n"
- $result.changed = $true
- }
-
- if ($null -ne $idle_timeout -and $idle_timeout -ne $cap.IdleTimeout) {
- $diff_text += "-IdleTimeout = $($cap.IdleTimeout)`n+IdleTimeout = $idle_timeout`n"
- Set-CAPPropertyValue -Name $name -Property IdleTimeout -Value $idle_timeout -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $allow_only_sdrts_servers -and $allow_only_sdrts_servers -ne $cap.AllowOnlySDRTSServers) {
- $diff_text += "-AllowOnlySDRTSServers = $($cap.AllowOnlySDRTSServers)`n+AllowOnlySDRTSServers = $allow_only_sdrts_servers`n"
- Set-CAPPropertyValue -Name $name -Property AllowOnlySDRTSServers -Value ([int]$allow_only_sdrts_servers) -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $redirect_clipboard -and $redirect_clipboard -ne $cap.DeviceRedirection.Clipboard) {
- $diff_text += "-RedirectClipboard = $($cap.DeviceRedirection.Clipboard)`n+RedirectClipboard = $redirect_clipboard`n"
- Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\Clipboard" -Value ([int]$redirect_clipboard) -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $redirect_drives -and $redirect_drives -ne $cap.DeviceRedirection.DiskDrives) {
- $diff_text += "-RedirectDrives = $($cap.DeviceRedirection.DiskDrives)`n+RedirectDrives = $redirect_drives`n"
- Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\DiskDrives" -Value ([int]$redirect_drives) -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $redirect_printers -and $redirect_printers -ne $cap.DeviceRedirection.Printers) {
- $diff_text += "-RedirectPrinters = $($cap.DeviceRedirection.Printers)`n+RedirectPrinters = $redirect_printers`n"
- Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\Printers" -Value ([int]$redirect_printers) -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $redirect_serial -and $redirect_serial -ne $cap.DeviceRedirection.SerialPorts) {
- $diff_text += "-RedirectSerial = $($cap.DeviceRedirection.SerialPorts)`n+RedirectSerial = $redirect_serial`n"
- Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\SerialPorts" -Value ([int]$redirect_serial) -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $redirect_pnp -and $redirect_pnp -ne $cap.DeviceRedirection.PlugAndPlayDevices) {
- $diff_text += "-RedirectPnP = $($cap.DeviceRedirection.PlugAndPlayDevices)`n+RedirectPnP = $redirect_pnp`n"
- Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\PlugAndPlayDevices" -Value ([int]$redirect_pnp) -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $user_groups) {
- $groups_to_remove = @($cap.UserGroups | Where-Object { $user_groups -notcontains $_ })
- $groups_to_add = @($user_groups | Where-Object { $cap.UserGroups -notcontains $_ })
-
- $user_groups_diff = $null
- foreach($group in $groups_to_add) {
- if (-not $check_mode) {
- $return = $wmi_cap | Invoke-CimMethod -MethodName AddUserGroupNames -Arguments @{ UserGroupNames = $group }
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to add user group $($group) (code: $($return.ReturnValue))"
- }
- }
- $user_groups_diff += " +$group`n"
- $result.changed = $true
- }
-
- foreach($group in $groups_to_remove) {
- if (-not $check_mode) {
- $return = $wmi_cap | Invoke-CimMethod -MethodName RemoveUserGroupNames -Arguments @{ UserGroupNames = $group }
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to remove user group $($group) (code: $($return.ReturnValue))"
- }
- }
- $user_groups_diff += " -$group`n"
- $result.changed = $true
- }
-
- if($user_groups_diff) {
- $diff_text += "~UserGroups`n$user_groups_diff"
- }
- }
-
- if ($null -ne $computer_groups) {
- $groups_to_remove = @($cap.ComputerGroups | Where-Object { $computer_groups -notcontains $_ })
- $groups_to_add = @($computer_groups | Where-Object { $cap.ComputerGroups -notcontains $_ })
-
- $computer_groups_diff = $null
- foreach($group in $groups_to_add) {
- if (-not $check_mode) {
- $return = $wmi_cap | Invoke-CimMethod -MethodName AddComputerGroupNames -Arguments @{ ComputerGroupNames = $group }
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to add computer group $($group) (code: $($return.ReturnValue))"
- }
- }
- $computer_groups_diff += " +$group`n"
- $result.changed = $true
- }
-
- foreach($group in $groups_to_remove) {
- if (-not $check_mode) {
- $return = $wmi_cap | Invoke-CimMethod -MethodName RemoveComputerGroupNames -Arguments @{ ComputerGroupNames = $group }
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to remove computer group $($group) (code: $($return.ReturnValue))"
- }
- }
- $computer_groups_diff += " -$group`n"
- $result.changed = $true
- }
-
- if($computer_groups_diff) {
- $diff_text += "~ComputerGroups`n$computer_groups_diff"
- }
- }
- }
-}
-
-if ($diff_mode -and $result.changed -eq $true) {
- $result.diff = @{
- prepared = $diff_text
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_rds_cap.py b/lib/ansible/modules/windows/win_rds_cap.py
deleted file mode 100644
index 6f5c587a79..0000000000
--- a/lib/ansible/modules/windows/win_rds_cap.py
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_rds_cap
-short_description: Manage Connection Authorization Policies (CAP) on a Remote Desktop Gateway server
-description:
- - Creates, removes and configures a Remote Desktop connection authorization policy (RD CAP).
- - A RD CAP allows you to specify the users who can connect to a Remote Desktop Gateway server.
-version_added: "2.8"
-author:
- - Kevin Subileau (@ksubileau)
-options:
- name:
- description:
- - Name of the connection authorization policy.
- type: str
- required: yes
- state:
- description:
- - The state of connection authorization policy.
- - If C(absent) will ensure the policy is removed.
- - If C(present) will ensure the policy is configured and exists.
- - If C(enabled) will ensure the policy is configured, exists and enabled.
- - If C(disabled) will ensure the policy is configured, exists, but disabled.
- type: str
- choices: [ absent, enabled, disabled, present ]
- default: present
- auth_method:
- description:
- - Specifies how the RD Gateway server authenticates users.
- - When a new CAP is created, the default value is C(password).
- type: str
- choices: [ both, none, password, smartcard ]
- order:
- description:
- - Evaluation order of the policy.
- - The CAP in which I(order) is set to a value of '1' is evaluated first.
- - By default, a newly created CAP will take the first position.
- - If the given value exceed the total number of existing policies,
- the policy will take the last position but the evaluation order
- will be capped to this number.
- type: int
- session_timeout:
- description:
- - The maximum time, in minutes, that a session can be idle.
- - A value of zero disables session timeout.
- type: int
- session_timeout_action:
- description:
- - The action the server takes when a session times out.
- - 'C(disconnect): disconnect the session.'
- - 'C(reauth): silently reauthenticate and reauthorize the session.'
- type: str
- choices: [ disconnect, reauth ]
- default: disconnect
- idle_timeout:
- description:
- - Specifies the time interval, in minutes, after which an idle session is disconnected.
- - A value of zero disables idle timeout.
- type: int
- allow_only_sdrts_servers:
- description:
- - Specifies whether connections are allowed only to Remote Desktop Session Host servers that
- enforce Remote Desktop Gateway redirection policy.
- type: bool
- user_groups:
- description:
- - A list of user groups that is allowed to connect to the Remote Gateway server.
- - Required when a new CAP is created.
- type: list
- computer_groups:
- description:
- - A list of computer groups that is allowed to connect to the Remote Gateway server.
- type: list
- redirect_clipboard:
- description:
- - Allow clipboard redirection.
- type: bool
- redirect_drives:
- description:
- - Allow disk drive redirection.
- type: bool
- redirect_printers:
- description:
- - Allow printers redirection.
- type: bool
- redirect_serial:
- description:
- - Allow serial port redirection.
- type: bool
- redirect_pnp:
- description:
- - Allow Plug and Play devices redirection.
- type: bool
-requirements:
- - Windows Server 2008R2 (6.1) or higher.
- - The Windows Feature "RDS-Gateway" must be enabled.
-seealso:
-- module: win_rds_cap
-- module: win_rds_rap
-- module: win_rds_settings
-'''
-
-EXAMPLES = r'''
-- name: Create a new RDS CAP with a 30 minutes timeout and clipboard redirection enabled
- win_rds_cap:
- name: My CAP
- user_groups:
- - BUILTIN\users
- session_timeout: 30
- session_timeout_action: disconnect
- allow_only_sdrts_servers: yes
- redirect_clipboard: yes
- redirect_drives: no
- redirect_printers: no
- redirect_serial: no
- redirect_pnp: no
- state: enabled
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_rds_rap.ps1 b/lib/ansible/modules/windows/win_rds_rap.ps1
deleted file mode 100644
index deb01a9c34..0000000000
--- a/lib/ansible/modules/windows/win_rds_rap.ps1
+++ /dev/null
@@ -1,282 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.SID
-
-$ErrorActionPreference = "Stop"
-
-# List of authentication methods as string. Used for parameter validation and conversion to integer flag, so order is important!
-$computer_group_types = @("rdg_group", "ad_network_resource_group", "allow_any")
-$computer_group_types_wmi = @{rdg_group = "RG"; ad_network_resource_group = "CG"; allow_any = "ALL"}
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
-
-$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
-$description = Get-AnsibleParam -obj $params -name "description" -type "str"
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent","present","enabled","disabled"
-$computer_group_type = Get-AnsibleParam -obj $params -name "computer_group_type" -type "str" -validateset $computer_group_types
-$computer_group = Get-AnsibleParam -obj $params -name "computer_group" -type "str" -failifempty ($computer_group_type -eq "ad_network_resource_group" -or $computer_group_type -eq "rdg_group")
-$user_groups = Get-AnsibleParam -obj $params -name "user_groups" -type "list"
-$allowed_ports = Get-AnsibleParam -obj $params -name "allowed_ports" -type "list"
-
-
-function Get-RAP([string] $name) {
- $rap_path = "RDS:\GatewayServer\RAP\$name"
- $rap = @{
- Name = $name
- }
-
- # Fetch RAP properties
- Get-ChildItem -Path $rap_path | ForEach-Object { $rap.Add($_.Name,$_.CurrentValue) }
- # Convert boolean values
- $rap.Enabled = $rap.Status -eq 1
- $rap.Remove("Status")
-
- # Convert computer group name from UPN to Down-Level Logon format
- if($rap.ComputerGroupType -ne 2) {
- $rap.ComputerGroup = Convert-FromSID -sid (Convert-ToSID -account_name $rap.ComputerGroup)
- }
-
- # Convert multiple choices values
- $rap.ComputerGroupType = $computer_group_types[$rap.ComputerGroupType]
-
- # Convert allowed ports from string to list
- if($rap.PortNumbers -eq '*') {
- $rap.PortNumbers = @("any")
- } else {
- $rap.PortNumbers = @($rap.PortNumbers -split ',')
- }
-
- # Fetch RAP user groups in Down-Level Logon format
- $rap.UserGroups = @(
- Get-ChildItem -Path "$rap_path\UserGroups" |
- Select-Object -ExpandProperty Name |
- ForEach-Object { Convert-FromSID -sid (Convert-ToSID -account_name $_) }
- )
-
- return $rap
-}
-
-function Set-RAPPropertyValue {
- [CmdletBinding(SupportsShouldProcess=$true)]
- param (
- [Parameter(Mandatory=$true)]
- [string] $name,
- [Parameter(Mandatory=$true)]
- [string] $property,
- [Parameter(Mandatory=$true)]
- $value,
- [Parameter()]
- $resultobj = @{}
- )
-
- $rap_path = "RDS:\GatewayServer\RAP\$name"
-
- try {
- Set-Item -Path "$rap_path\$property" -Value $value -ErrorAction stop
- } catch {
- Fail-Json -obj $resultobj -message "Failed to set property $property of RAP ${name}: $($_.Exception.Message)"
- }
-}
-
-$result = @{
- changed = $false
-}
-$diff_text = $null
-
-# Validate RAP name
-if ($name -match "[*/\\;:?`"<>|\t]+") {
- Fail-Json -obj $result -message "Invalid character in RAP name."
-}
-
-# Validate user groups
-if ($null -ne $user_groups) {
- if ($user_groups.Count -lt 1) {
- Fail-Json -obj $result -message "Parameter 'user_groups' cannot be an empty list."
- }
-
- $user_groups = $user_groups | ForEach-Object {
- $group = $_
- # Test that the group is resolvable on the local machine
- $sid = Convert-ToSID -account_name $group
- if (!$sid) {
- Fail-Json -obj $result -message "$group is not a valid user group on the host machine or domain."
- }
-
- # Return the normalized group name in Down-Level Logon format
- Convert-FromSID -sid $sid
- }
- $user_groups = @($user_groups)
-}
-
-# Validate computer group parameter
-if ($computer_group_type -eq "allow_any" -and $null -ne $computer_group) {
- Add-Warning -obj $result -message "Parameter 'computer_group' ignored because the computer_group_type is set to allow_any."
-} elseif ($computer_group_type -eq "rdg_group" -and -not (Test-Path -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\$computer_group")) {
- Fail-Json -obj $result -message "$computer_group is not a valid gateway managed computer group"
-} elseif ($computer_group_type -eq "ad_network_resource_group") {
- $sid = Convert-ToSID -account_name $computer_group
- if (!$sid) {
- Fail-Json -obj $result -message "$computer_group is not a valid computer group on the host machine or domain."
- }
- # Ensure the group name is in Down-Level Logon format
- $computer_group = Convert-FromSID -sid $sid
-}
-
-# Validate port numbers
-if ($null -ne $allowed_ports) {
- foreach ($port in $allowed_ports) {
- if (-not ($port -eq "any" -or ($port -is [int] -and $port -ge 1 -and $port -le 65535))) {
- Fail-Json -obj $result -message "$port is not a valid port number."
- }
- }
-}
-
-# Ensure RemoteDesktopServices module is loaded
-if ($null -eq (Get-Module -Name RemoteDesktopServices -ErrorAction SilentlyContinue)) {
- Import-Module -Name RemoteDesktopServices
-}
-
-# Check if a RAP with the given name already exists
-$rap_exist = Test-Path -Path "RDS:\GatewayServer\RAP\$name"
-
-if ($state -eq 'absent') {
- if ($rap_exist) {
- Remove-Item -Path "RDS:\GatewayServer\RAP\$name" -Recurse -WhatIf:$check_mode
- $diff_text += "-[$name]"
- $result.changed = $true
- }
-} else {
- $diff_text_added_prefix = ''
- if (-not $rap_exist) {
- if ($null -eq $user_groups) {
- Fail-Json -obj $result -message "User groups must be defined to create a new RAP."
- }
-
- # Computer group type is required when creating a new RAP. Set it to allow connect to any resource by default.
- if ($null -eq $computer_group_type) {
- $computer_group_type = "allow_any"
- }
-
- # Create a new RAP
- if (-not $check_mode) {
- $RapArgs = @{
- Name = $name
- ResourceGroupType = 'ALL'
- UserGroupNames = $user_groups -join ';'
- ProtocolNames = 'RDP'
- PortNumbers = '*'
- }
- $return = Invoke-CimMethod -Namespace Root\CIMV2\TerminalServices -ClassName Win32_TSGatewayResourceAuthorizationPolicy -MethodName Create -Arguments $RapArgs
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to create RAP $name (code: $($return.ReturnValue))"
- }
- }
- $rap_exist = -not $check_mode
-
- $diff_text_added_prefix = '+'
- $result.changed = $true
- }
-
- $diff_text += "$diff_text_added_prefix[$name]`n"
-
- # We cannot configure a RAP that was created above in check mode as it won't actually exist
- if($rap_exist) {
- $rap = Get-RAP -Name $name
- $wmi_rap = Get-CimInstance -ClassName Win32_TSGatewayResourceAuthorizationPolicy -Namespace Root\CIMv2\TerminalServices -Filter "name='$($name)'"
-
- if ($state -in @('disabled', 'enabled')) {
- $rap_enabled = $state -ne 'disabled'
- if ($rap.Enabled -ne $rap_enabled) {
- $diff_text += "-State = $(@('disabled', 'enabled')[[int]$rap.Enabled])`n+State = $state`n"
- Set-RAPPropertyValue -Name $name -Property Status -Value ([int]$rap_enabled) -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
- }
-
- if ($null -ne $description -and $description -ne $rap.Description) {
- Set-RAPPropertyValue -Name $name -Property Description -Value $description -ResultObj $result -WhatIf:$check_mode
- $diff_text += "-Description = $($rap.Description)`n+Description = $description`n"
- $result.changed = $true
- }
-
- if ($null -ne $allowed_ports -and @(Compare-Object $rap.PortNumbers $allowed_ports -SyncWindow 0).Count -ne 0) {
- $diff_text += "-AllowedPorts = [$($rap.PortNumbers -join ',')]`n+AllowedPorts = [$($allowed_ports -join ',')]`n"
- if ($allowed_ports -contains 'any') { $allowed_ports = '*' }
- Set-RAPPropertyValue -Name $name -Property PortNumbers -Value $allowed_ports -ResultObj $result -WhatIf:$check_mode
- $result.changed = $true
- }
-
- if ($null -ne $computer_group_type -and $computer_group_type -ne $rap.ComputerGroupType) {
- $diff_text += "-ComputerGroupType = $($rap.ComputerGroupType)`n+ComputerGroupType = $computer_group_type`n"
- if ($computer_group_type -ne "allow_any") {
- $diff_text += "+ComputerGroup = $computer_group`n"
- }
- $return = $wmi_rap | Invoke-CimMethod -MethodName SetResourceGroup -Arguments @{
- ResourceGroupName = $computer_group
- ResourceGroupType = $computer_group_types_wmi.$($computer_group_type)
- }
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to set computer group type to $($computer_group_type) (code: $($return.ReturnValue))"
- }
-
- $result.changed = $true
-
- } elseif ($null -ne $computer_group -and $computer_group -ne $rap.ComputerGroup) {
- $diff_text += "-ComputerGroup = $($rap.ComputerGroup)`n+ComputerGroup = $computer_group`n"
- $return = $wmi_rap | Invoke-CimMethod -MethodName SetResourceGroup -Arguments @{
- ResourceGroupName = $computer_group
- ResourceGroupType = $computer_group_types_wmi.$($rap.ComputerGroupType)
- }
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to set computer group name to $($computer_group) (code: $($return.ReturnValue))"
- }
- $result.changed = $true
- }
-
- if ($null -ne $user_groups) {
- $groups_to_remove = @($rap.UserGroups | Where-Object { $user_groups -notcontains $_ })
- $groups_to_add = @($user_groups | Where-Object { $rap.UserGroups -notcontains $_ })
-
- $user_groups_diff = $null
- foreach($group in $groups_to_add) {
- if (-not $check_mode) {
- $return = $wmi_rap | Invoke-CimMethod -MethodName AddUserGroupNames -Arguments @{ UserGroupNames = $group }
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to add user group $($group) (code: $($return.ReturnValue))"
- }
- }
- $user_groups_diff += " +$group`n"
- $result.changed = $true
- }
-
- foreach($group in $groups_to_remove) {
- if (-not $check_mode) {
- $return = $wmi_rap | Invoke-CimMethod -MethodName RemoveUserGroupNames -Arguments @{ UserGroupNames = $group }
- if ($return.ReturnValue -ne 0) {
- Fail-Json -obj $result -message "Failed to remove user group $($group) (code: $($return.ReturnValue))"
- }
- }
- $user_groups_diff += " -$group`n"
- $result.changed = $true
- }
-
- if($user_groups_diff) {
- $diff_text += "~UserGroups`n$user_groups_diff"
- }
- }
- }
-}
-
-if ($diff_mode -and $result.changed -eq $true) {
- $result.diff = @{
- prepared = $diff_text
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_rds_rap.py b/lib/ansible/modules/windows/win_rds_rap.py
deleted file mode 100644
index c6e60be102..0000000000
--- a/lib/ansible/modules/windows/win_rds_rap.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_rds_rap
-short_description: Manage Resource Authorization Policies (RAP) on a Remote Desktop Gateway server
-description:
- - Creates, removes and configures a Remote Desktop resource authorization policy (RD RAP).
- - A RD RAP allows you to specify the network resources (computers) that users can connect
- to remotely through a Remote Desktop Gateway server.
-version_added: "2.8"
-author:
- - Kevin Subileau (@ksubileau)
-options:
- name:
- description:
- - Name of the resource authorization policy.
- required: yes
- state:
- description:
- - The state of resource authorization policy.
- - If C(absent) will ensure the policy is removed.
- - If C(present) will ensure the policy is configured and exists.
- - If C(enabled) will ensure the policy is configured, exists and enabled.
- - If C(disabled) will ensure the policy is configured, exists, but disabled.
- type: str
- choices: [ absent, disabled, enabled, present ]
- default: present
- description:
- description:
- - Optional description of the resource authorization policy.
- type: str
- user_groups:
- description:
- - List of user groups that are associated with this resource authorization policy (RAP).
- A user must belong to one of these groups to access the RD Gateway server.
- - Required when a new RAP is created.
- type: list
- allowed_ports:
- description:
- - List of port numbers through which connections are allowed for this policy.
- - To allow connections through any port, specify 'any'.
- type: list
- computer_group_type:
- description:
- - 'The computer group type:'
- - 'C(rdg_group): RD Gateway-managed group'
- - 'C(ad_network_resource_group): Active Directory Domain Services network resource group'
- - 'C(allow_any): Allow users to connect to any network resource.'
- type: str
- choices: [ rdg_group, ad_network_resource_group, allow_any ]
- computer_group:
- description:
- - The computer group name that is associated with this resource authorization policy (RAP).
- - This is required when I(computer_group_type) is C(rdg_group) or C(ad_network_resource_group).
- type: str
-requirements:
- - Windows Server 2008R2 (6.1) or higher.
- - The Windows Feature "RDS-Gateway" must be enabled.
-seealso:
-- module: win_rds_cap
-- module: win_rds_rap
-- module: win_rds_settings
-'''
-
-EXAMPLES = r'''
-- name: Create a new RDS RAP
- win_rds_rap:
- name: My RAP
- description: Allow all users to connect to any resource through ports 3389 and 3390
- user_groups:
- - BUILTIN\users
- computer_group_type: allow_any
- allowed_ports:
- - 3389
- - 3390
- state: enabled
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_rds_settings.ps1 b/lib/ansible/modules/windows/win_rds_settings.ps1
deleted file mode 100644
index 7a31fe1275..0000000000
--- a/lib/ansible/modules/windows/win_rds_settings.ps1
+++ /dev/null
@@ -1,100 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-# List of ssl bridging methods as string. Used for parameter validation and conversion to integer flag, so order is important!
-$ssl_bridging_methods = @("none", "https_http", "https_https")
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
-
-$certificate = Get-AnsibleParam $params -name "certificate_hash" -type "str"
-$max_connections = Get-AnsibleParam $params -name "max_connections" -type "int"
-$ssl_bridging = Get-AnsibleParam -obj $params -name "ssl_bridging" -type "str" -validateset $ssl_bridging_methods
-$enable_only_messaging_capable_clients = Get-AnsibleParam $params -name "enable_only_messaging_capable_clients" -type "bool"
-
-$result = @{
- changed = $false
-}
-$diff_text = $null
-
-# Ensure RemoteDesktopServices module is loaded
-if ($null -eq (Get-Module -Name RemoteDesktopServices -ErrorAction SilentlyContinue)) {
- Import-Module -Name RemoteDesktopServices
-}
-
-if ($null -ne $certificate)
-{
- # Validate cert path
- $cert_path = "cert:\LocalMachine\My\$certificate"
- If (-not (Test-Path $cert_path) )
- {
- Fail-Json -obj $result -message "Unable to locate certificate at $cert_path"
- }
-
- # Get current certificate hash
- $current_cert = (Get-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint").CurrentValue
- if ($current_cert -ne $certificate) {
- Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $certificate -WhatIf:$check_mode
- $diff_text += "-Certificate = $current_cert`n+Certificate = $certificate`n"
- $result.changed = $true
- }
-}
-
-if ($null -ne $max_connections)
-{
- # Set the correct value for unlimited connections
- # TODO Use a more explicit value, maybe a string (ex: "max", "none" or "unlimited") ?
- If ($max_connections -eq -1)
- {
- $max_connections = (Get-Item -Path "RDS:\GatewayServer\MaxConnectionsAllowed").CurrentValue
- }
-
- # Get current connections limit
- $current_max_connections = (Get-Item -Path "RDS:\GatewayServer\MaxConnections").CurrentValue
- if ($current_max_connections -ne $max_connections) {
- Set-Item -Path "RDS:\GatewayServer\MaxConnections" -Value $max_connections -WhatIf:$check_mode
- $diff_text += "-MaxConnections = $current_max_connections`n+MaxConnections = $max_connections`n"
- $result.changed = $true
- }
-}
-
-if ($null -ne $ssl_bridging)
-{
- $current_ssl_bridging = (Get-Item -Path "RDS:\GatewayServer\SSLBridging").CurrentValue
- # Convert the integer value to its representative string
- $current_ssl_bridging_str = $ssl_bridging_methods[$current_ssl_bridging]
-
- if ($current_ssl_bridging_str -ne $ssl_bridging) {
- Set-Item -Path "RDS:\GatewayServer\SSLBridging" -Value ([array]::IndexOf($ssl_bridging_methods, $ssl_bridging)) -WhatIf:$check_mode
- $diff_text += "-SSLBridging = $current_ssl_bridging_str`n+SSLBridging = $ssl_bridging`n"
- $result.changed = $true
- }
-}
-
-if ($null -ne $enable_only_messaging_capable_clients)
-{
- $current_enable_only_messaging_capable_clients = (Get-Item -Path "RDS:\GatewayServer\EnableOnlyMessagingCapableClients").CurrentValue
- # Convert the integer value to boolean
- $current_enable_only_messaging_capable_clients = $current_enable_only_messaging_capable_clients -eq 1
-
- if ($current_enable_only_messaging_capable_clients -ne $enable_only_messaging_capable_clients) {
- Set-Item -Path "RDS:\GatewayServer\EnableOnlyMessagingCapableClients" -Value ([int]$enable_only_messaging_capable_clients) -WhatIf:$check_mode
- $diff_text += "-EnableOnlyMessagingCapableClients = $current_enable_only_messaging_capable_clients`n+EnableOnlyMessagingCapableClients = $enable_only_messaging_capable_clients`n"
- $result.changed = $true
- }
-}
-
-if ($diff_mode -and $result.changed -eq $true) {
- $result.diff = @{
- prepared = $diff_text
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_rds_settings.py b/lib/ansible/modules/windows/win_rds_settings.py
deleted file mode 100644
index 5919a816e1..0000000000
--- a/lib/ansible/modules/windows/win_rds_settings.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_rds_settings
-short_description: Manage main settings of a Remote Desktop Gateway server
-description:
- - Configure general settings of a Remote Desktop Gateway server.
-version_added: "2.8"
-author:
- - Kevin Subileau (@ksubileau)
-options:
- certificate_hash:
- description:
- - Certificate hash (thumbprint) for the Remote Desktop Gateway server. The certificate hash is the unique identifier for the certificate.
- type: str
- max_connections:
- description:
- - The maximum number of connections allowed.
- - If set to C(0), no new connections are allowed.
- - If set to C(-1), the number of connections is unlimited.
- type: int
- ssl_bridging:
- description:
- - Specifies whether to use SSL Bridging.
- - 'C(none): no SSL bridging.'
- - 'C(https_http): HTTPS-HTTP bridging.'
- - 'C(https_https): HTTPS-HTTPS bridging.'
- type: str
- choices: [ https_http, https_https, none ]
- enable_only_messaging_capable_clients:
- description:
- - If enabled, only clients that support logon messages and administrator messages can connect.
- type: bool
-requirements:
- - Windows Server 2008R2 (6.1) or higher.
- - The Windows Feature "RDS-Gateway" must be enabled.
-seealso:
-- module: win_rds_cap
-- module: win_rds_rap
-- module: win_rds_settings
-'''
-
-EXAMPLES = r'''
-- name: Configure the Remote Desktop Gateway
- win_rds_settings:
- certificate_hash: B0D0FA8408FC67B230338FCA584D03792DA73F4C
- max_connections: 50
- notify:
- - Restart TSGateway service
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_region.ps1 b/lib/ansible/modules/windows/win_region.ps1
deleted file mode 100644
index 7542a8b1d1..0000000000
--- a/lib/ansible/modules/windows/win_region.ps1
+++ /dev/null
@@ -1,365 +0,0 @@
-#!powershell
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params "_ansible_check_mode" -type 'bool' -default $false
-$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
-
-$location = Get-AnsibleParam -obj $params -name 'location' -type 'str'
-$format = Get-AnsibleParam -obj $params -name 'format' -type 'str'
-$unicode_language = Get-AnsibleParam -obj $params -name 'unicode_language' -type 'str'
-$copy_settings = Get-AnsibleParam -obj $params -name 'copy_settings' -type 'bool' -default $false
-
-$result = @{
- changed = $false
- restart_required = $false
-}
-
-# This is used to get the format values based on the LCType enum based through. When running Vista/7/2008/200R2
-$lctype_util = @"
-using System;
-using System.Text;
-using System.Runtime.InteropServices;
-using System.ComponentModel;
-
-namespace Ansible.WinRegion {
-
- public class NativeMethods
- {
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern int GetLocaleInfoEx(
- String lpLocaleName,
- UInt32 LCType,
- StringBuilder lpLCData,
- int cchData);
-
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern int GetSystemDefaultLocaleName(
- IntPtr lpLocaleName,
- int cchLocaleName);
-
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern int GetUserDefaultLocaleName(
- IntPtr lpLocaleName,
- int cchLocaleName);
- }
-
- public class LocaleHelper {
- private String Locale;
-
- public LocaleHelper(String locale) {
- Locale = locale;
- }
-
- public String GetValueFromType(UInt32 LCType) {
- StringBuilder data = new StringBuilder(500);
- int result = NativeMethods.GetLocaleInfoEx(Locale, LCType, data, 500);
- if (result == 0)
- throw new Exception(String.Format("Error getting locale info with legacy method: {0}", new Win32Exception(Marshal.GetLastWin32Error()).Message));
-
- return data.ToString();
- }
- }
-}
-"@
-$original_tmp = $env:TMP
-$env:TMP = $_remote_tmp
-Add-Type -TypeDefinition $lctype_util
-$env:TMP = $original_tmp
-
-Function Get-LastWin32ExceptionMessage {
- param([int]$ErrorCode)
- $exp = New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $ErrorCode
- $exp_msg = "{0} (Win32 ErrorCode {1} - 0x{1:X8})" -f $exp.Message, $ErrorCode
- return $exp_msg
-}
-
-Function Get-SystemLocaleName {
- $max_length = 85 # LOCALE_NAME_MAX_LENGTH
- $ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($max_length)
-
- try {
- $res = [Ansible.WinRegion.NativeMethods]::GetSystemDefaultLocaleName($ptr, $max_length)
-
- if ($res -eq 0) {
- $err_code = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- $msg = Get-LastWin32ExceptionMessage -Error $err_code
- Fail-Json -obj $result -message "Failed to get system locale: $msg"
- }
-
- $system_locale = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr)
- } finally {
- [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)
- }
-
- return $system_locale
-}
-
-Function Get-UserLocaleName {
- $max_length = 85 # LOCALE_NAME_MAX_LENGTH
- $ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($max_length)
-
- try {
- $res = [Ansible.WinRegion.NativeMethods]::GetUserDefaultLocaleName($ptr, $max_length)
-
- if ($res -eq 0) {
- $err_code = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
- $msg = Get-LastWin32ExceptionMessage -Error $err_code
- Fail-Json -obj $result -message "Failed to get user locale: $msg"
- }
-
- $user_locale = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ptr)
- } finally {
- [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr)
- }
-
- return $user_locale
-}
-
-Function Get-ValidGeoIds($cultures) {
- $geo_ids = @()
- foreach($culture in $cultures) {
- try {
- $geo_id = [System.Globalization.RegionInfo]$culture.Name
- $geo_ids += $geo_id.GeoId
- } catch {}
- }
- $geo_ids
-}
-
-Function Test-RegistryProperty($reg_key, $property) {
- $type = Get-ItemProperty $reg_key -Name $property -ErrorAction SilentlyContinue
- if ($null -eq $type) {
- $false
- } else {
- $true
- }
-}
-
-Function Copy-RegistryKey($source, $target) {
- # Using Copy-Item -Recurse is giving me weird results, doing it recursively
- Copy-Item -Path $source -Destination $target -WhatIf:$check_mode
-
- foreach($key in Get-ChildItem $source) {
- $sourceKey = "$source\$($key.PSChildName)"
- $targetKey = (Get-Item $source).PSChildName
- Copy-RegistryKey -source "$sourceKey" -target "$target\$targetKey"
- }
-}
-
-Function Set-UserLocale($culture) {
- $reg_key = 'HKCU:\Control Panel\International'
-
- $lookup = New-Object Ansible.WinRegion.LocaleHelper($culture)
- # hex values are from http://www.pinvoke.net/default.aspx/kernel32/GetLocaleInfoEx.html
- $wanted_values = @{
- Locale = '{0:x8}' -f ([System.Globalization.CultureInfo]$culture).LCID
- LocaleName = $culture
- s1159 = $lookup.GetValueFromType(0x00000028)
- s2359 = $lookup.GetValueFromType(0x00000029)
- sCountry = $lookup.GetValueFromType(0x00000006)
- sCurrency = $lookup.GetValueFromType(0x00000014)
- sDate = $lookup.GetValueFromType(0x0000001D)
- sDecimal = $lookup.GetValueFromType(0x0000000E)
- sGrouping = $lookup.GetValueFromType(0x00000010)
- sLanguage = $lookup.GetValueFromType(0x00000003) # LOCALE_ABBREVLANGNAME
- sList = $lookup.GetValueFromType(0x0000000C)
- sLongDate = $lookup.GetValueFromType(0x00000020)
- sMonDecimalSep = $lookup.GetValueFromType(0x00000016)
- sMonGrouping = $lookup.GetValueFromType(0x00000018)
- sMonThousandSep = $lookup.GetValueFromType(0x00000017)
- sNativeDigits = $lookup.GetValueFromType(0x00000013)
- sNegativeSign = $lookup.GetValueFromType(0x00000051)
- sPositiveSign = $lookup.GetValueFromType(0x00000050)
- sShortDate = $lookup.GetValueFromType(0x0000001F)
- sThousand = $lookup.GetValueFromType(0x0000000F)
- sTime = $lookup.GetValueFromType(0x0000001E)
- sTimeFormat = $lookup.GetValueFromType(0x00001003)
- sYearMonth = $lookup.GetValueFromType(0x00001006)
- iCalendarType = $lookup.GetValueFromType(0x00001009)
- iCountry = $lookup.GetValueFromType(0x00000005)
- iCurrDigits = $lookup.GetValueFromType(0x00000019)
- iCurrency = $lookup.GetValueFromType(0x0000001B)
- iDate = $lookup.GetValueFromType(0x00000021)
- iDigits = $lookup.GetValueFromType(0x00000011)
- NumShape = $lookup.GetValueFromType(0x00001014) # LOCALE_IDIGITSUBSTITUTION
- iFirstDayOfWeek = $lookup.GetValueFromType(0x0000100C)
- iFirstWeekOfYear = $lookup.GetValueFromType(0x0000100D)
- iLZero = $lookup.GetValueFromType(0x00000012)
- iMeasure = $lookup.GetValueFromType(0x0000000D)
- iNegCurr = $lookup.GetValueFromType(0x0000001C)
- iNegNumber = $lookup.GetValueFromType(0x00001010)
- iPaperSize = $lookup.GetValueFromType(0x0000100A)
- iTime = $lookup.GetValueFromType(0x00000023)
- iTimePrefix = $lookup.GetValueFromType(0x00001005)
- iTLZero = $lookup.GetValueFromType(0x00000025)
- }
-
- if (Test-RegistryProperty -reg_key $reg_key -property 'sShortTime') {
- # sShortTime was added after Vista, will check anyway and add in the value if it exists
- $wanted_values.sShortTime = $lookup.GetValueFromType(0x00000079)
- }
-
- $properties = Get-ItemProperty $reg_key
- foreach($property in $properties.PSObject.Properties) {
- if (Test-RegistryProperty -reg_key $reg_key -property $property.Name) {
- $name = $property.Name
- $old_value = $property.Value
- $new_value = $wanted_values.$name
-
- if ($new_value -ne $old_value) {
- Set-ItemProperty -Path $reg_key -Name $name -Value $new_value -WhatIf:$check_mode
- $result.changed = $true
- }
- }
- }
-}
-
-Function Set-SystemLocaleLegacy($unicode_language) {
- # For when Get/Set-WinSystemLocale is not available (Pre Windows 8 and Server 2012)
- $current_language_value = (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\Language').Default
- $wanted_language_value = '{0:x4}' -f ([System.Globalization.CultureInfo]$unicode_language).LCID
- if ($current_language_value -ne $wanted_language_value) {
- Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\Language' -Name 'Default' -Value $wanted_language_value -WhatIf:$check_mode
- $result.changed = $true
- $result.restart_required = $true
- }
-
- # This reads from the non registry (Default) key, the extra prop called (Default) see below for more details
- $current_locale_value = (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\Locale')."(Default)"
- $wanted_locale_value = '{0:x8}' -f ([System.Globalization.CultureInfo]$unicode_language).LCID
- if ($current_locale_value -ne $wanted_locale_value) {
- # Need to use .net to write property value, Locale has 2 (Default) properties
- # 1: The actual (Default) property, we don't want to change Set-ItemProperty writes to this value when using (Default)
- # 2: A property called (Default), this is what we want to change and only .net SetValue can do this one
- if (-not $check_mode) {
- $hive = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $env:COMPUTERNAME)
- $key = $hive.OpenSubKey("SYSTEM\CurrentControlSet\Control\Nls\Locale", $true)
- $key.SetValue("(Default)", $wanted_locale_value, [Microsoft.Win32.RegistryValueKind]::String)
- }
- $result.changed = $true
- $result.restart_required = $true
- }
-
- $codepage_path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage'
- $current_codepage_info = Get-ItemProperty $codepage_path
- $wanted_codepage_info = ([System.Globalization.CultureInfo]::GetCultureInfo($unicode_language)).TextInfo
-
- $current_a_cp = $current_codepage_info.ACP
- $current_oem_cp = $current_codepage_info.OEMCP
- $current_mac_cp = $current_codepage_info.MACCP
- $wanted_a_cp = $wanted_codepage_info.ANSICodePage
- $wanted_oem_cp = $wanted_codepage_info.OEMCodePage
- $wanted_mac_cp = $wanted_codepage_info.MacCodePage
-
- if ($current_a_cp -ne $wanted_a_cp) {
- Set-ItemProperty -Path $codepage_path -Name 'ACP' -Value $wanted_a_cp -WhatIf:$check_mode
- $result.changed = $true
- $result.restart_required = $true
- }
- if ($current_oem_cp -ne $wanted_oem_cp) {
- Set-ItemProperty -Path $codepage_path -Name 'OEMCP' -Value $wanted_oem_cp -WhatIf:$check_mode
- $result.changed = $true
- $result.restart_required = $true
- }
- if ($current_mac_cp -ne $wanted_mac_cp) {
- Set-ItemProperty -Path $codepage_path -Name 'MACCP' -Value $wanted_mac_cp -WhatIf:$check_mode
- $result.changed = $true
- $result.restart_required = $true
- }
-}
-
-if ($null -eq $format -and $null -eq $location -and $null -eq $unicode_language) {
- Fail-Json $result "An argument for 'format', 'location' or 'unicode_language' needs to be supplied"
-} else {
- $valid_cultures = [System.Globalization.CultureInfo]::GetCultures('InstalledWin32Cultures')
- $valid_geoids = Get-ValidGeoIds -cultures $valid_cultures
-
- if ($null -ne $location) {
- if ($valid_geoids -notcontains $location) {
- Fail-Json $result "The argument location '$location' does not contain a valid Geo ID"
- }
- }
-
- if ($null -ne $format) {
- if ($valid_cultures.Name -notcontains $format) {
- Fail-Json $result "The argument format '$format' does not contain a valid Culture Name"
- }
- }
-
- if ($null -ne $unicode_language) {
- if ($valid_cultures.Name -notcontains $unicode_language) {
- Fail-Json $result "The argument unicode_language '$unicode_language' does not contain a valid Culture Name"
- }
- }
-}
-
-if ($null -ne $location) {
- # Get-WinHomeLocation was only added in Server 2012 and above
- # Use legacy option if older
- if (Get-Command 'Get-WinHomeLocation' -ErrorAction SilentlyContinue) {
- $current_location = (Get-WinHomeLocation).GeoId
- if ($current_location -ne $location) {
- if (-not $check_mode) {
- Set-WinHomeLocation -GeoId $location
- }
- $result.changed = $true
- }
- } else {
- $current_location = (Get-ItemProperty -Path 'HKCU:\Control Panel\International\Geo').Nation
- if ($current_location -ne $location) {
- Set-ItemProperty -Path 'HKCU:\Control Panel\International\Geo' -Name 'Nation' -Value $location -WhatIf:$check_mode
- $result.changed = $true
- }
- }
-}
-
-if ($null -ne $format) {
- # Cannot use Get/Set-Culture as that fails to get and set the culture when running in the PSRP runspace.
- $current_format = Get-UserLocaleName
- if ($current_format -ne $format) {
- Set-UserLocale -culture $format
- $result.changed = $true
- }
-}
-
-if ($null -ne $unicode_language) {
- # Get/Set-WinSystemLocale was only added in Server 2012 and above, use legacy option if older
- if (Get-Command 'Get-WinSystemLocale' -ErrorAction SilentlyContinue) {
- $current_unicode_language = Get-SystemLocaleName
- if ($current_unicode_language -ne $unicode_language) {
- if (-not $check_mode) {
- Set-WinSystemLocale -SystemLocale $unicode_language
- }
- $result.changed = $true
- $result.restart_required = $true
- }
- } else {
- Set-SystemLocaleLegacy -unicode_language $unicode_language
- }
-}
-
-if ($copy_settings -eq $true -and $result.changed -eq $true) {
- if (-not $check_mode) {
- $defaultHiveKey = 'HKU\TEMP'
- reg load $defaultHiveKey 'C:\Users\Default\NTUSER.DAT'
- New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS
-
- $sids = 'TEMP', '.DEFAULT', 'S-1-5-19', 'S-1-5-20'
- foreach ($sid in $sids) {
- Copy-RegistryKey -source "HKCU:\Keyboard Layout" -target "HKU:\$sid"
- Copy-RegistryKey -source "HKCU:\Control Panel\International" -target "HKU:\$sid\Control Panel"
- Copy-RegistryKey -source "HKCU:\Control Panel\Input Method" -target "HKU:\$sid\Control Panel"
- }
-
- Remove-PSDrive HKU
- [gc]::collect()
- reg unload $defaultHiveKey
- }
- $result.changed = $true
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_region.py b/lib/ansible/modules/windows/win_region.py
deleted file mode 100644
index 84ef3be080..0000000000
--- a/lib/ansible/modules/windows/win_region.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2016, Ansible, inc
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
-module: win_region
-version_added: "2.3"
-short_description: Set the region and format settings
-description:
- - Set the location settings of a Windows Server.
- - Set the format settings of a Windows Server.
- - Set the unicode language settings of a Windows Server.
- - Copy across these settings to the default profile.
-options:
- location:
- description:
- - The location to set for the current user, see
- U(https://msdn.microsoft.com/en-us/library/dd374073.aspx)
- for a list of GeoIDs you can use and what location it relates to.
- - This needs to be set if C(format) or C(unicode_language) is not
- set.
- type: str
- format:
- description:
- - The language format to set for the current user, see
- U(https://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx)
- for a list of culture names to use.
- - This needs to be set if C(location) or C(unicode_language) is not set.
- type: str
- unicode_language:
- description:
- - The unicode language format to set for all users, see
- U(https://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx)
- for a list of culture names to use.
- - This needs to be set if C(location) or C(format) is not set. After setting this
- value a reboot is required for it to take effect.
- type: str
- copy_settings:
- description:
- - This will copy the current format and location values to new user
- profiles and the welcome screen. This will only run if
- C(location), C(format) or C(unicode_language) has resulted in a
- change. If this process runs then it will always result in a
- change.
- type: bool
- default: no
-seealso:
-- module: win_timezone
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Set the region format to English United States
- win_region:
- format: en-US
-
-- name: Set the region format to English Australia and copy settings to new profiles
- win_region:
- format: en-AU
- copy_settings: yes
-
-- name: Set the location to United States
- win_region:
- location: 244
-
-# Reboot when region settings change
-- name: Set the unicode language to English Great Britain, reboot if required
- win_region:
- unicode_language: en-GB
- register: result
-
-- win_reboot:
- when: result.restart_required
-
-# Reboot when format, location or unicode has changed
-- name: Set format, location and unicode to English Australia and copy settings, reboot if required
- win_region:
- location: 12
- format: en-AU
- unicode_language: en-AU
- register: result
-
-- win_reboot:
- when: result.restart_required
-'''
-
-RETURN = r'''
-restart_required:
- description: Whether a reboot is required for the change to take effect.
- returned: success
- type: bool
- sample: true
-'''
diff --git a/lib/ansible/modules/windows/win_regmerge.ps1 b/lib/ansible/modules/windows/win_regmerge.ps1
deleted file mode 100644
index 44c3ae1b1e..0000000000
--- a/lib/ansible/modules/windows/win_regmerge.ps1
+++ /dev/null
@@ -1,97 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Jon Hawkesworth (@jhawkesworth) <figs@unity.demon.co.uk>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.ArgvParser
-#Requires -Module Ansible.ModuleUtils.CommandUtil
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-Function Convert-RegistryPath {
- Param (
- [parameter(Mandatory=$True)]
- [ValidateNotNullOrEmpty()]$Path
- )
-
- $output = $Path -replace "HKLM:", "HKLM"
- $output = $output -replace "HKCU:", "HKCU"
-
- Return $output
-}
-
-$result = @{
- changed = $false
-}
-$params = Parse-Args $args
-
-$path = Get-AnsibleParam -obj $params -name "path" -type "path" -failifempty $true -resultobj $result
-$compare_to = Get-AnsibleParam -obj $params -name "compare_to" -type "str" -resultobj $result
-
-# check it looks like a reg key, warn if key not present - will happen first time
-# only accepting PS-Drive style key names (starting with HKLM etc, not HKEY_LOCAL_MACHINE etc)
-
-$do_comparison = $False
-
-If ($compare_to) {
- $compare_to_key = $params.compare_to.ToString()
- If (Test-Path $compare_to_key -pathType container ) {
- $do_comparison = $True
- } Else {
- $result.compare_to_key_found = $false
- }
-}
-
-If ( $do_comparison -eq $True ) {
- $guid = [guid]::NewGuid()
- $exported_path = $env:TEMP + "\" + $guid.ToString() + 'ansible_win_regmerge.reg'
-
- $expanded_compare_key = Convert-RegistryPath ($compare_to_key)
-
- # export from the reg key location to a file
- $reg_args = Argv-ToString -Arguments @("reg.exe", "EXPORT", $expanded_compare_key, $exported_path)
- $res = Run-Command -command $reg_args
- if ($res.rc -ne 0) {
- $result.rc = $res.rc
- $result.stdout = $res.stdout
- $result.stderr = $res.stderr
- Fail-Json -obj $result -message "error exporting registry '$expanded_compare_key' to '$exported_path'"
- }
-
- # compare the two files
- $comparison_result = Compare-Object -ReferenceObject $(Get-Content $path) -DifferenceObject $(Get-Content $exported_path)
-
- If ($null -ne $comparison_result -and (Get-Member -InputObject $comparison_result -Name "count" -MemberType Properties ))
- {
- # Something is different, actually do reg merge
- $reg_import_args = Argv-ToString -Arguments @("reg.exe", "IMPORT", $path)
- $res = Run-Command -command $reg_import_args
- if ($res.rc -ne 0) {
- $result.rc = $res.rc
- $result.stdout = $res.stdout
- $result.stderr = $res.stderr
- Fail-Json -obj $result -message "error importing registry values from '$path'"
- }
- $result.changed = $true
- $result.difference_count = $comparison_result.count
- } Else {
- $result.difference_count = 0
- }
-
- Remove-Item $exported_path
- $result.compared = $true
-
-} Else {
- # not comparing, merge and report changed
- $reg_import_args = Argv-ToString -Arguments @("reg.exe", "IMPORT", $path)
- $res = Run-Command -command $reg_import_args
- if ($res.rc -ne 0) {
- $result.rc = $res.rc
- $result.stdout = $res.stdout
- $result.stderr = $res.stderr
- Fail-Json -obj $result -message "error importing registry value from '$path'"
- }
- $result.changed = $true
- $result.compared = $false
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_regmerge.py b/lib/ansible/modules/windows/win_regmerge.py
deleted file mode 100644
index 1b5596f945..0000000000
--- a/lib/ansible/modules/windows/win_regmerge.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Jon Hawkesworth (@jhawkesworth) <figs@unity.demon.co.uk>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_regmerge
-version_added: "2.1"
-short_description: Merges the contents of a registry file into the Windows registry
-description:
- - Wraps the reg.exe command to import the contents of a registry file.
- - Suitable for use with registry files created using M(win_template).
- - Windows registry files have a specific format and must be constructed correctly with carriage return and line feed line endings otherwise they will not
- be merged.
- - Exported registry files often start with a Byte Order Mark which must be removed if the file is to templated using M(win_template).
- - Registry file format is described at U(https://support.microsoft.com/en-us/kb/310516)
- - See also M(win_template), M(win_regedit)
-options:
- path:
- description:
- - The full path including file name to the registry file on the remote machine to be merged
- type: path
- required: yes
- compare_key:
- description:
- - The parent key to use when comparing the contents of the registry to the contents of the file. Needs to be in HKLM or HKCU part of registry.
- Use a PS-Drive style path for example HKLM:\SOFTWARE not HKEY_LOCAL_MACHINE\SOFTWARE
- If not supplied, or the registry key is not found, no comparison will be made, and the module will report changed.
- type: str
-notes:
- - Organise your registry files so that they contain a single root registry
- key if you want to use the compare_to functionality.
- - This module does not force registry settings to be in the state
- described in the file. If registry settings have been modified externally
- the module will merge the contents of the file but continue to report
- differences on subsequent runs.
- - To force registry change, use M(win_regedit) with C(state=absent) before
- using C(win_regmerge).
-seealso:
-- module: win_reg_stat
-- module: win_regedit
-author:
-- Jon Hawkesworth (@jhawkesworth)
-'''
-
-EXAMPLES = r'''
-- name: Merge in a registry file without comparing to current registry
- win_regmerge:
- path: C:\autodeploy\myCompany-settings.reg
-
-- name: Compare and merge registry file
- win_regmerge:
- path: C:\autodeploy\myCompany-settings.reg
- compare_to: HKLM:\SOFTWARE\myCompany
-'''
-
-RETURN = r'''
-compare_to_key_found:
- description: whether the parent registry key has been found for comparison
- returned: when comparison key not found in registry
- type: bool
- sample: false
-difference_count:
- description: number of differences between the registry and the file
- returned: changed
- type: int
- sample: 1
-compared:
- description: whether a comparison has taken place between the registry and the file
- returned: when a comparison key has been supplied and comparison has been attempted
- type: bool
- sample: true
-'''
diff --git a/lib/ansible/modules/windows/win_robocopy.ps1 b/lib/ansible/modules/windows/win_robocopy.ps1
deleted file mode 100644
index 6ef83e299e..0000000000
--- a/lib/ansible/modules/windows/win_robocopy.ps1
+++ /dev/null
@@ -1,145 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Corwin Brown <corwin.brown@maxpoint.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$src = Get-AnsibleParam -obj $params -name "src" -type "path" -failifempty $true
-$dest = Get-AnsibleParam -obj $params -name "dest" -type "path" -failifempty $true
-$purge = Get-AnsibleParam -obj $params -name "purge" -type "bool" -default $false
-$recurse = Get-AnsibleParam -obj $params -name "recurse" -type "bool" -default $false
-$flags = Get-AnsibleParam -obj $params -name "flags" -type "str"
-
-$result = @{
- changed = $false
- dest = $dest
- purge = $purge
- recurse = $recurse
- src = $src
-}
-
-# Search for an Error Message
-# Robocopy seems to display an error after 3 '-----' separator lines
-Function SearchForError($cmd_output, $default_msg) {
- $separator_count = 0
- $error_msg = $default_msg
- ForEach ($line in $cmd_output) {
- if (-not $line) {
- continue
- }
-
- if ($separator_count -ne 3) {
- if (Select-String -InputObject $line -pattern "^(\s+)?(\-+)(\s+)?$") {
- $separator_count += 1
- }
- } else {
- if (Select-String -InputObject $line -pattern "error") {
- $error_msg = $line
- break
- }
- }
- }
-
- return $error_msg
-}
-
-if (-not (Test-Path -Path $src)) {
- Fail-Json $result "$src does not exist!"
-}
-
-# Build Arguments
-$robocopy_opts = @($src, $dest)
-
-if ($check_mode) {
- $robocopy_opts += "/l"
-}
-
-if ($null -eq $flags) {
- if ($purge) {
- $robocopy_opts += "/purge"
- }
-
- if ($recurse) {
- $robocopy_opts += "/e"
- }
-} else {
- ForEach ($f in $flags.split(" ")) {
- $robocopy_opts += $f
- }
-}
-
-$result.flags = $flags
-$result.cmd = "$robocopy $robocopy_opts"
-
-Try {
- $robocopy_output = &robocopy $robocopy_opts
- $rc = $LASTEXITCODE
-} Catch {
- Fail-Json $result "Error synchronizing $src to $dest! Msg: $($_.Exception.Message)"
-}
-
-$result.msg = "Success"
-$result.output = $robocopy_output
-$result.return_code = $rc # Backward compatibility
-$result.rc = $rc
-
-switch ($rc) {
-
- 0 {
- $result.msg = "No files copied."
- }
- 1 {
- $result.msg = "Files copied successfully!"
- $result.changed = $true
- $result.failed = $false
- }
- 2 {
- $result.msg = "Some Extra files or directories were detected. No files were copied."
- Add-Warning $result $result.msg
- $result.failed = $false
- }
- 3 {
- $result.msg = "(2+1) Some files were copied. Additional files were present."
- Add-Warning $result $result.msg
- $result.changed = $true
- $result.failed = $false
- }
- 4 {
- $result.msg = "Some mismatched files or directories were detected. Housekeeping might be required!"
- Add-Warning $result $result.msg
- $result.changed = $true
- $result.failed = $false
- }
- 5 {
- $result.msg = "(4+1) Some files were copied. Some files were mismatched."
- Add-Warning $result $result.msg
- $result.changed = $true
- $result.failed = $false
- }
- 6 {
- $result.msg = "(4+2) Additional files and mismatched files exist. No files were copied."
- $result.failed = $false
- }
- 7 {
- $result.msg = "(4+1+2) Files were copied, a file mismatch was present, and additional files were present."
- Add-Warning $result $result.msg
- $result.changed = $true
- $result.failed = $false
- }
- 8 {
- Fail-Json $result (SearchForError $robocopy_output "Some files or directories could not be copied!")
- }
- { @(9, 10, 11, 12, 13, 14, 15) -contains $_ } {
- Fail-Json $result (SearchForError $robocopy_output "Fatal error. Check log message!")
- }
- 16 {
- Fail-Json $result (SearchForError $robocopy_output "Serious Error! No files were copied! Do you have permissions to access $src and $dest?")
- }
-
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_robocopy.py b/lib/ansible/modules/windows/win_robocopy.py
deleted file mode 100644
index f652f151a3..0000000000
--- a/lib/ansible/modules/windows/win_robocopy.py
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Corwin Brown <blakfeld@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_robocopy
-version_added: '2.2'
-short_description: Synchronizes the contents of two directories using Robocopy
-description:
-- Synchronizes the contents of files/directories from a source to destination.
-- Under the hood this just calls out to RoboCopy, since that should be available
- on most modern Windows systems.
-options:
- src:
- description:
- - Source file/directory to sync.
- type: path
- required: yes
- dest:
- description:
- - Destination file/directory to sync (Will receive contents of src).
- type: path
- required: yes
- recurse:
- description:
- - Includes all subdirectories (Toggles the C(/e) flag to RoboCopy).
- - If C(flags) is set, this will be ignored.
- type: bool
- default: no
- purge:
- description:
- - Deletes any files/directories found in the destination that do not exist in the source.
- - Toggles the C(/purge) flag to RoboCopy.
- - If C(flags) is set, this will be ignored.
- type: bool
- default: no
- flags:
- description:
- - Directly supply Robocopy flags.
- - If set, C(purge) and C(recurse) will be ignored.
- type: str
-notes:
-- This is not a complete port of the M(synchronize) module. Unlike the M(synchronize) module this only performs the sync/copy on the remote machine,
- not from the master to the remote machine.
-- This module does not currently support all Robocopy flags.
-seealso:
-- module: synchronize
-- module: win_copy
-author:
-- Corwin Brown (@blakfeld)
-'''
-
-EXAMPLES = r'''
-- name: Sync the contents of one directory to another
- win_robocopy:
- src: C:\DirectoryOne
- dest: C:\DirectoryTwo
-
-- name: Sync the contents of one directory to another, including subdirectories
- win_robocopy:
- src: C:\DirectoryOne
- dest: C:\DirectoryTwo
- recurse: yes
-
-- name: Sync the contents of one directory to another, and remove any files/directories found in destination that do not exist in the source
- win_robocopy:
- src: C:\DirectoryOne
- dest: C:\DirectoryTwo
- purge: yes
-
-- name: Sync content in recursive mode, removing any files/directories found in destination that do not exist in the source
- win_robocopy:
- src: C:\DirectoryOne
- dest: C:\DirectoryTwo
- recurse: yes
- purge: yes
-
-- name: Sync two directories in recursive and purging mode, specifying additional special flags
- win_robocopy:
- src: C:\DirectoryOne
- dest: C:\DirectoryTwo
- flags: /E /PURGE /XD SOME_DIR /XF SOME_FILE /MT:32
-
-- name: Sync one file from a remote UNC path in recursive and purging mode, specifying additional special flags
- win_robocopy:
- src: \\Server1\Directory One
- dest: C:\DirectoryTwo
- flags: file.zip /E /PURGE /XD SOME_DIR /XF SOME_FILE /MT:32
-'''
-
-RETURN = r'''
-cmd:
- description: The used command line.
- returned: always
- type: str
- sample: robocopy C:\DirectoryOne C:\DirectoryTwo /e /purge
-src:
- description: The Source file/directory of the sync.
- returned: always
- type: str
- sample: C:\Some\Path
-dest:
- description: The Destination file/directory of the sync.
- returned: always
- type: str
- sample: C:\Some\Path
-recurse:
- description: Whether or not the recurse flag was toggled.
- returned: always
- type: bool
- sample: false
-purge:
- description: Whether or not the purge flag was toggled.
- returned: always
- type: bool
- sample: false
-flags:
- description: Any flags passed in by the user.
- returned: always
- type: str
- sample: /e /purge
-rc:
- description: The return code returned by robocopy.
- returned: success
- type: int
- sample: 1
-output:
- description: The output of running the robocopy command.
- returned: success
- type: str
- sample: "------------------------------------\\n ROBOCOPY :: Robust File Copy for Windows \\n------------------------------------\\n "
-msg:
- description: Output interpreted into a concise message.
- returned: always
- type: str
- sample: No files copied!
-'''
diff --git a/lib/ansible/modules/windows/win_route.ps1 b/lib/ansible/modules/windows/win_route.ps1
deleted file mode 100644
index f74d482be2..0000000000
--- a/lib/ansible/modules/windows/win_route.ps1
+++ /dev/null
@@ -1,104 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2016, Daniele Lazzari <lazzari@mailup.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-# win_route (Add or remove a network static route)
-
-$params = Parse-Args $args -supports_check_mode $true
-
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -default $false
-$dest = Get-AnsibleParam -obj $params -name "destination" -type "str" -failifempty $true
-$gateway = Get-AnsibleParam -obj $params -name "gateway" -type "str"
-$metric = Get-AnsibleParam -obj $params -name "metric" -type "int" -default 1
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateSet "present","absent"
-$result = @{
- "changed" = $false
- "output" = ""
- }
-
-Function Add-Route {
- Param (
- [Parameter(Mandatory=$true)]
- [string]$Destination,
- [Parameter(Mandatory=$true)]
- [string]$Gateway,
- [Parameter(Mandatory=$true)]
- [int]$Metric,
- [Parameter(Mandatory=$true)]
- [bool]$CheckMode
- )
-
-
- $IpAddress = $Destination.split('/')[0]
-
- # Check if the static route is already present
- $Route = Get-CimInstance win32_ip4PersistedrouteTable -Filter "Destination = '$($IpAddress)'"
- if (!($Route)){
- try {
- # Find Interface Index
- $InterfaceIndex = Find-NetRoute -RemoteIPAddress $Gateway | Select-Object -First 1 -ExpandProperty InterfaceIndex
-
- # Add network route
- New-NetRoute -DestinationPrefix $Destination -NextHop $Gateway -InterfaceIndex $InterfaceIndex -RouteMetric $Metric -ErrorAction Stop -WhatIf:$CheckMode|out-null
- $result.changed = $true
- $result.output = "Route added"
-
- }
- catch {
- $ErrorMessage = $_.Exception.Message
- Fail-Json $result $ErrorMessage
- }
- }
- else {
- $result.output = "Static route already exists"
- }
-
-}
-
-Function Remove-Route {
- Param (
- [Parameter(Mandatory=$true)]
- [string]$Destination,
- [bool]$CheckMode
- )
- $IpAddress = $Destination.split('/')[0]
- $Route = Get-CimInstance win32_ip4PersistedrouteTable -Filter "Destination = '$($IpAddress)'"
- if ($Route){
- try {
-
- Remove-NetRoute -DestinationPrefix $Destination -Confirm:$false -ErrorAction Stop -WhatIf:$CheckMode
- $result.changed = $true
- $result.output = "Route removed"
- }
- catch {
- $ErrorMessage = $_.Exception.Message
- Fail-Json $result $ErrorMessage
- }
- }
- else {
- $result.output = "No route to remove"
- }
-
-}
-
-# Set gateway if null
-if(!($gateway)){
- $gateway = "0.0.0.0"
-}
-
-
-if ($state -eq "present"){
-
- Add-Route -Destination $dest -Gateway $gateway -Metric $metric -CheckMode $check_mode
-
-}
-else {
-
- Remove-Route -Destination $dest -CheckMode $check_mode
-
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_route.py b/lib/ansible/modules/windows/win_route.py
deleted file mode 100644
index 51e0366ad9..0000000000
--- a/lib/ansible/modules/windows/win_route.py
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Daniele Lazzari <lazzari@mailup.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# This is a windows documentation stub. Actual code lives in the .ps1
-# file of the same name.
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_route
-version_added: "2.4"
-short_description: Add or remove a static route
-description:
- - Add or remove a static route.
-options:
- destination:
- description:
- - Destination IP address in CIDR format (ip address/prefix length).
- type: str
- required: yes
- gateway:
- description:
- - The gateway used by the static route.
- - If C(gateway) is not provided it will be set to C(0.0.0.0).
- type: str
- metric:
- description:
- - Metric used by the static route.
- type: int
- default: 1
- state:
- description:
- - If C(absent), it removes a network static route.
- - If C(present), it adds a network static route.
- type: str
- choices: [ absent, present ]
- default: present
-notes:
- - Works only with Windows 2012 R2 and newer.
-author:
-- Daniele Lazzari (@dlazz)
-'''
-
-EXAMPLES = r'''
----
-- name: Add a network static route
- win_route:
- destination: 192.168.2.10/32
- gateway: 192.168.1.1
- metric: 1
- state: present
-
-- name: Remove a network static route
- win_route:
- destination: 192.168.2.10/32
- state: absent
-'''
-RETURN = r'''
-output:
- description: A message describing the task result.
- returned: always
- type: str
- sample: "Route added"
-'''
diff --git a/lib/ansible/modules/windows/win_say.ps1 b/lib/ansible/modules/windows/win_say.ps1
deleted file mode 100644
index 253402b5ec..0000000000
--- a/lib/ansible/modules/windows/win_say.ps1
+++ /dev/null
@@ -1,95 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2016, Jon Hawkesworth (@jhawkesworth) <figs@unity.demon.co.uk>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-$spec = @{
- options = @{
- msg = @{ type = "str" }
- msg_file = @{ type = "path" }
- start_sound_path = @{ type = "path" }
- end_sound_path = @{ type = "path" }
- voice = @{ type = "str" }
- speech_speed = @{ type = "int"; default = 0 }
- }
- mutually_exclusive = @(
- ,@('msg', 'msg_file')
- )
- required_one_of = @(
- ,@('msg', 'msg_file', 'start_sound_path', 'end_sound_path')
- )
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-
-$msg = $module.Params.msg
-$msg_file = $module.Params.msg_file
-$start_sound_path = $module.Params.start_sound_path
-$end_sound_path = $module.Params.end_sound_path
-$voice = $module.Params.voice
-$speech_speed = $module.Params.speech_speed
-
-if ($speech_speed -lt -10 -or $speech_speed -gt 10) {
- $module.FailJson("speech_speed needs to be an integer in the range -10 to 10. The value $speech_speed is outside this range.")
-}
-
-$words = $null
-
-if ($msg_file) {
- if (-not (Test-Path -Path $msg_file)) {
- $module.FailJson("Message file $msg_file could not be found or opened. Ensure you have specified the full path to the file, and the ansible windows user has permission to read the file.")
- }
- $words = Get-Content $msg_file | Out-String
-}
-
-if ($msg) {
- $words = $msg
-}
-
-if ($start_sound_path) {
- if (-not (Test-Path -Path $start_sound_path)) {
- $module.FailJson("Start sound file $start_sound_path could not be found or opened. Ensure you have specified the full path to the file, and the ansible windows user has permission to read the file.")
- }
- if (-not $module.CheckMode) {
- (new-object Media.SoundPlayer $start_sound_path).playSync()
- }
-}
-
-if ($words) {
- Add-Type -AssemblyName System.speech
- $tts = New-Object System.Speech.Synthesis.SpeechSynthesizer
- if ($voice) {
- try {
- $tts.SelectVoice($voice)
- } catch [System.Management.Automation.MethodInvocationException] {
- $module.Result.voice_info = "Could not load voice '$voice', using system default voice."
- $module.Warn("Could not load voice '$voice', using system default voice.")
- }
- }
-
- $module.Result.voice = $tts.Voice.Name
- if ($speech_speed -ne 0) {
- $tts.Rate = $speech_speed
- }
- if (-not $module.CheckMode) {
- $tts.Speak($words)
- }
- $tts.Dispose()
-}
-
-if ($end_sound_path) {
- if (-not (Test-Path -Path $end_sound_path)) {
- $module.FailJson("End sound file $start_sound_path could not be found or opened. Ensure you have specified the full path to the file, and the ansible windows user has permission to read the file.")
- }
- if (-not $module.CheckMode) {
- (new-object Media.SoundPlayer $end_sound_path).playSync()
- }
-}
-
-$module.Result.message_text = $words.ToString()
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_say.py b/lib/ansible/modules/windows/win_say.py
deleted file mode 100644
index 877fe4f913..0000000000
--- a/lib/ansible/modules/windows/win_say.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2016, Jon Hawkesworth (@jhawkesworth) <figs@unity.demon.co.uk>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_say
-version_added: "2.3"
-short_description: Text to speech module for Windows to speak messages and optionally play sounds
-description:
- - Uses .NET libraries to convert text to speech and optionally play .wav sounds. Audio Service needs to be running and some kind of speakers or
- headphones need to be attached to the windows target(s) for the speech to be audible.
-options:
- msg:
- description:
- - The text to be spoken.
- - Use either C(msg) or C(msg_file).
- - Optional so that you can use this module just to play sounds.
- type: str
- msg_file:
- description:
- - Full path to a windows format text file containing the text to be spoken.
- - Use either C(msg) or C(msg_file).
- - Optional so that you can use this module just to play sounds.
- type: path
- voice:
- description:
- - Which voice to use. See notes for how to discover installed voices.
- - If the requested voice is not available the default voice will be used.
- Example voice names from Windows 10 are C(Microsoft Zira Desktop) and C(Microsoft Hazel Desktop).
- type: str
- speech_speed:
- description:
- - How fast or slow to speak the text.
- - Must be an integer value in the range -10 to 10.
- - -10 is slowest, 10 is fastest.
- type: int
- default: 0
- start_sound_path:
- description:
- - Full path to a C(.wav) file containing a sound to play before the text is spoken.
- - Useful on conference calls to alert other speakers that ansible has something to say.
- type: path
- end_sound_path:
- description:
- - Full path to a C(.wav) file containing a sound to play after the text has been spoken.
- - Useful on conference calls to alert other speakers that ansible has finished speaking.
- type: path
-notes:
- - Needs speakers or headphones to do anything useful.
- - |
- To find which voices are installed, run the following Powershell commands.
-
- Add-Type -AssemblyName System.Speech
- $speech = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
- $speech.GetInstalledVoices() | ForEach-Object { $_.VoiceInfo }
- $speech.Dispose()
-
- - Speech can be surprisingly slow, so it's best to keep message text short.
-seealso:
-- module: win_msg
-- module: win_toast
-author:
-- Jon Hawkesworth (@jhawkesworth)
-'''
-
-EXAMPLES = r'''
-- name: Warn of impending deployment
- win_say:
- msg: Warning, deployment commencing in 5 minutes, please log out.
-
-- name: Using a different voice and a start sound
- win_say:
- start_sound_path: C:\Windows\Media\ding.wav
- msg: Warning, deployment commencing in 5 minutes, please log out.
- voice: Microsoft Hazel Desktop
-
-- name: With start and end sound
- win_say:
- start_sound_path: C:\Windows\Media\Windows Balloon.wav
- msg: New software installed
- end_sound_path: C:\Windows\Media\chimes.wav
-
-- name: Text from file example
- win_say:
- start_sound_path: C:\Windows\Media\Windows Balloon.wav
- msg_file: AppData\Local\Temp\morning_report.txt
- end_sound_path: C:\Windows\Media\chimes.wav
-'''
-
-RETURN = r'''
-message_text:
- description: The text that the module attempted to speak.
- returned: success
- type: str
- sample: "Warning, deployment commencing in 5 minutes."
-voice:
- description: The voice used to speak the text.
- returned: success
- type: str
- sample: Microsoft Hazel Desktop
-voice_info:
- description: The voice used to speak the text.
- returned: when requested voice could not be loaded
- type: str
- sample: Could not load voice TestVoice, using system default voice
-'''
diff --git a/lib/ansible/modules/windows/win_scheduled_task.ps1 b/lib/ansible/modules/windows/win_scheduled_task.ps1
deleted file mode 100644
index ac5938d266..0000000000
--- a/lib/ansible/modules/windows/win_scheduled_task.ps1
+++ /dev/null
@@ -1,1133 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Peter Mounce <public@neverrunwithscissors.com>
-# Copyright: (c) 2015, Michael Perzel <michaelperzel@gmail.com>
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.SID
-
-$ErrorActionPreference = "Stop"
-
-$params = Parse-Args -arguments $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
-$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
-
-$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
-$path = Get-AnsibleParam -obj $params -name "path" -type "str" -default "\"
-$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent", "present"
-
-# task actions, list of dicts [{path, arguments, working_directory}]
-$actions = Get-AnsibleParam -obj $params -name "actions" -type "list"
-
-# task triggers, list of dicts [{ type, ... }]
-$triggers = Get-AnsibleParam -obj $params -name "triggers" -type "list"
-
-# task Principal properties
-$display_name = Get-AnsibleParam -obj $params -name "display_name" -type "str"
-$group = Get-AnsibleParam -obj $params -name "group" -type "str"
-$logon_type = Get-AnsibleParam -obj $params -name "logon_type" -type "str" -validateset "none","password","s4u","interactive_token","group","service_account","interactive_token_or_password"
-$run_level = Get-AnsibleParam -obj $params -name "run_level" -type "str" -validateset "limited", "highest" -aliases "runlevel"
-$username = Get-AnsibleParam -obj $params -name "username" -type "str" -aliases "user"
-$password = Get-AnsibleParam -obj $params -name "password" -type "str"
-$update_password = Get-AnsibleParam -obj $params -name "update_password" -type "bool" -default $true
-
-# task RegistrationInfo properties
-$author = Get-AnsibleParam -obj $params -name "author" -type "str"
-$date = Get-AnsibleParam -obj $params -name "date" -type "str"
-$description = Get-AnsibleParam -obj $params -name "description" -type "str"
-$source = Get-AnsibleParam -obj $params -name "source" -type "str"
-$version = Get-AnsibleParam -obj $params -name "version" -type "str"
-
-# task Settings properties
-$allow_demand_start = Get-AnsibleParam -obj $params -name "allow_demand_start" -type "bool"
-$allow_hard_terminate = Get-AnsibleParam -obj $params -name "allow_hard_terminate" -type "bool"
-$compatibility = Get-AnsibleParam -obj $params -name "compatibility" -type "int" # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383486(v=vs.85).aspx
-$delete_expired_task_after = Get-AnsibleParam -obj $params -name "delete_expired_task_after" -type "str" # time string PT...
-$disallow_start_if_on_batteries = Get-AnsibleParam -obj $params -name "disallow_start_if_on_batteries" -type "bool"
-$enabled = Get-AnsibleParam -obj $params -name "enabled" -type "bool"
-$execution_time_limit = Get-AnsibleParam -obj $params -name "execution_time_limit" -type "str" # PT72H
-$hidden = Get-AnsibleParam -obj $params -name "hidden" -type "bool"
-# TODO: support for $idle_settings, needs to be created as a COM object
-$multiple_instances = Get-AnsibleParam -obj $params -name "multiple_instances" -type "int" # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383507(v=vs.85).aspx
-# TODO: support for $network_settings, needs to be created as a COM object
-$priority = Get-AnsibleParam -obj $params -name "priority" -type "int" # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383512(v=vs.85).aspx
-$restart_count = Get-AnsibleParam -obj $params -name "restart_count" -type "int"
-$restart_interval = Get-AnsibleParam -obj $params -name "restart_interval" -type "str" # time string PT..
-$run_only_if_idle = Get-AnsibleParam -obj $params -name "run_only_if_idle" -type "bool"
-$run_only_if_network_available = Get-AnsibleParam -obj $params -name "run_only_if_network_available" -type "bool"
-$start_when_available = Get-AnsibleParam -obj $params -name "start_when_available" -type "bool"
-$stop_if_going_on_batteries = Get-AnsibleParam -obj $params -name "stop_if_going_on_batteries" -type "bool"
-$wake_to_run = Get-AnsibleParam -obj $params -name "wake_to_run" -type "bool"
-
-$result = @{
- changed = $false
-}
-
-if ($diff_mode) {
- $result.diff = @{}
-}
-
-$task_enums = @"
-public enum TASK_ACTION_TYPE // https://msdn.microsoft.com/en-us/library/windows/desktop/aa383553(v=vs.85).aspx
-{
- TASK_ACTION_EXEC = 0,
- // The below are not supported and are only kept for documentation purposes
- TASK_ACTION_COM_HANDLER = 5,
- TASK_ACTION_SEND_EMAIL = 6,
- TASK_ACTION_SHOW_MESSAGE = 7
-}
-
-public enum TASK_CREATION // https://msdn.microsoft.com/en-us/library/windows/desktop/aa382538(v=vs.85).aspx
-{
- TASK_VALIDATE_ONLY = 0x1,
- TASK_CREATE = 0x2,
- TASK_UPDATE = 0x4,
- TASK_CREATE_OR_UPDATE = 0x6,
- TASK_DISABLE = 0x8,
- TASK_DONT_ADD_PRINCIPAL_ACE = 0x10,
- TASK_IGNORE_REGISTRATION_TRIGGERS = 0x20
-}
-
-public enum TASK_LOGON_TYPE // https://msdn.microsoft.com/en-us/library/windows/desktop/aa383566(v=vs.85).aspx
-{
- TASK_LOGON_NONE = 0,
- TASK_LOGON_PASSWORD = 1,
- TASK_LOGON_S4U = 2,
- TASK_LOGON_INTERACTIVE_TOKEN = 3,
- TASK_LOGON_GROUP = 4,
- TASK_LOGON_SERVICE_ACCOUNT = 5,
- TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD = 6
-}
-
-public enum TASK_RUN_LEVEL // https://msdn.microsoft.com/en-us/library/windows/desktop/aa380747(v=vs.85).aspx
-{
- TASK_RUNLEVEL_LUA = 0,
- TASK_RUNLEVEL_HIGHEST = 1
-}
-
-public enum TASK_TRIGGER_TYPE2 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa383915(v=vs.85).aspx
-{
- TASK_TRIGGER_EVENT = 0,
- TASK_TRIGGER_TIME = 1,
- TASK_TRIGGER_DAILY = 2,
- TASK_TRIGGER_WEEKLY = 3,
- TASK_TRIGGER_MONTHLY = 4,
- TASK_TRIGGER_MONTHLYDOW = 5,
- TASK_TRIGGER_IDLE = 6,
- TASK_TRIGGER_REGISTRATION = 7,
- TASK_TRIGGER_BOOT = 8,
- TASK_TRIGGER_LOGON = 9,
- TASK_TRIGGER_SESSION_STATE_CHANGE = 11
-}
-"@
-
-$original_tmp = $env:TMP
-$env:TMP = $_remote_tmp
-Add-Type -TypeDefinition $task_enums
-$env:TMP = $original_tmp
-
-########################
-### HELPER FUNCTIONS ###
-########################
-Function Convert-SnakeToPascalCase($snake) {
- # very basic function to convert snake_case to PascalCase for use in COM
- # objects
- [regex]$regex = "_(\w)"
- $pascal_case = $regex.Replace($snake, { $args[0].Value.Substring(1).ToUpper() })
- $capitalised = $pascal_case.Substring(0, 1).ToUpper() + $pascal_case.Substring(1)
-
- return $capitalised
-}
-
-Function Compare-Properties($property_name, $parent_property, $map, $enum_map=$null) {
- $changes = [System.Collections.ArrayList]@()
-
- # loop through the passed in map and compare values
- # Name = The name of property in the COM object
- # Value = The new value to compare the existing value with
- foreach ($entry in $map.GetEnumerator()) {
- $new_value = $entry.Value
-
- if ($null -ne $new_value) {
- $property_name = $entry.Name
- $existing_value = $parent_property.$property_name
- if ($existing_value -cne $new_value) {
- try {
- $parent_property.$property_name = $new_value
- } catch {
- Fail-Json -obj $result -message "failed to set $property_name property '$property_name' to '$new_value': $($_.Exception.Message)"
- }
-
- if ($null -ne $enum_map -and $enum_map.ContainsKey($property_name)) {
- $enum = [type]$enum_map.$property_name
- $existing_value = [Enum]::ToObject($enum, $existing_value)
- $new_value = [Enum]::ToObject($enum, $new_value)
- }
- [void]$changes.Add("-$property_name=$existing_value`n+$property_name=$new_value")
- }
- }
- }
-
- return ,$changes
-}
-
-Function Set-PropertyForComObject($com_object, $name, $arg, $value) {
- $com_name = Convert-SnakeToPascalCase -snake $arg
- try {
- $com_object.$com_name = $value
- } catch {
- Fail-Json -obj $result -message "failed to set $name property '$com_name' to '$value': $($_.Exception.Message)"
- }
-}
-
-Function Compare-PropertyList {
- Param(
- $collection, # the collection COM object to manipulate, this must contains the Create method
- [string]$property_name, # human friendly name of the property object, e.g. action/trigger
- [Array]$new, # a list of new properties, passed in by Ansible
- [Array]$existing, # a list of existing properties from the COM object collection
- [Hashtable]$map, # metadata for the collection, see below for the structure
- [string]$enum # the parent enum name for type value
- )
- <## map metadata structure
- {
- collection type [TASK_ACTION_TYPE] for Actions or [TASK_TRIGGER_TYPE2] for Triggers {
- mandatory = list of mandatory properties for this type, ansible input name not the COM name
- optional = list of optional properties that could be set for this type
- # maps the ansible input object name to the COM name, e.g. working_directory = WorkingDirectory
- map = {
- ansible input name = COM name
- }
- }
- }##>
- # used by both Actions and Triggers to compare the collections of that property
-
- $enum = [type]$enum
- $changes = [System.Collections.ArrayList]@()
- $new_count = $new.Count
- $existing_count = $existing.Count
-
- for ($i = 0; $i -lt $new_count; $i++) {
- if ($i -lt $existing_count) {
- $existing_property = $existing[$i]
- } else {
- $existing_property = $null
- }
- $new_property = $new[$i]
-
- # get the type of the property, for action this is set automatically
- if (-not $new_property.ContainsKey("type")) {
- Fail-Json -obj $result -message "entry for $property_name must contain a type key"
- }
- $type = $new_property.type
- $valid_types = $map.Keys
- $property_map = $map.$type
-
- # now let's validate the args for the property
- $mandatory_args = $property_map.mandatory
- $optional_args = $property_map.optional
- $total_args = $mandatory_args + $optional_args
-
- # validate the mandatory arguments
- foreach ($mandatory_arg in $mandatory_args) {
- if (-not $new_property.ContainsKey($mandatory_arg)) {
- Fail-Json -obj $result -message "mandatory key '$mandatory_arg' for $($property_name) is not set, mandatory keys are '$($mandatory_args -join "', '")'"
- }
- }
- # throw a warning if in invalid key was set
- foreach ($entry in $new_property.GetEnumerator()) {
- $key = $entry.Name
- if ($key -notin $total_args -and $key -ne "type") {
- Add-Warning -obj $result -message "key '$key' for $($property_name) entry is not valid and will be ignored, valid keys are '$($total_args -join "', '")'"
- }
- }
-
- # now we have validated the input and have gotten the metadata, let's
- # get the diff string
- if ($null -eq $existing_property) {
- # we have more properties than before,just add to the new
- # properties list
- $diff_list = [System.Collections.ArrayList]@()
-
- foreach ($property_arg in $total_args) {
- if ($new_property.ContainsKey($property_arg)) {
- $com_name = Convert-SnakeToPascalCase -snake $property_arg
- $property_value = $new_property.$property_arg
-
- if ($property_value -is [Hashtable]) {
- foreach ($kv in $property_value.GetEnumerator()) {
- $sub_com_name = Convert-SnakeToPascalCase -snake $kv.Key
- $sub_property_value = $kv.Value
- [void]$diff_list.Add("+$com_name.$sub_com_name=$sub_property_value")
- }
- } else {
- [void]$diff_list.Add("+$com_name=$property_value")
- }
- }
- }
-
- [void]$changes.Add("+$property_name[$i] = {`n +Type=$type`n $($diff_list -join ",`n ")`n+}")
- } elseif ([Enum]::ToObject($enum, $existing_property.Type) -ne $type) {
- # the types are different so we need to change
- $diff_list = [System.Collections.ArrayList]@()
-
- if ($existing_property.Type -notin $valid_types) {
- [void]$diff_list.Add("-UNKNOWN TYPE $($existing_property.Type)")
- foreach ($property_args in $total_args) {
- if ($new_property.ContainsKey($property_arg)) {
- $com_name = Convert-SnakeToPascalCase -snake $property_arg
- $property_value = $new_property.$property_arg
-
- if ($property_value -is [Hashtable]) {
- foreach ($kv in $property_value.GetEnumerator()) {
- $sub_com_name = Convert-SnakeToPascalCase -snake $kv.Key
- $sub_property_value = $kv.Value
- [void]$diff_list.Add("+$com_name.$sub_com_name=$sub_property_value")
- }
- } else {
- [void]$diff_list.Add("+$com_name=$property_value")
- }
- }
- }
- } else {
- # we know the types of the existing property
- $existing_type = [Enum]::ToObject([TASK_TRIGGER_TYPE2], $existing_property.Type)
- [void]$diff_list.Add("-Type=$existing_type")
- [void]$diff_list.Add("+Type=$type")
- foreach ($property_arg in $total_args) {
- $com_name = Convert-SnakeToPascalCase -snake $property_arg
- $property_value = $new_property.$property_arg
- $existing_value = $existing_property.$com_name
-
- if ($property_value -is [Hashtable]) {
- foreach ($kv in $property_value.GetEnumerator()) {
- $sub_property_value = $kv.Value
- $sub_com_name = Convert-SnakeToPascalCase -snake $kv.Key
- $sub_existing_value = $existing_property.$com_name.$sub_com_name
-
- if ($null -ne $sub_property_value) {
- [void]$diff_list.Add("+$com_name.$sub_com_name=$sub_property_value")
- }
-
- if ($null -ne $sub_existing_value) {
- [void]$diff_list.Add("-$com_name.$sub_com_name=$sub_existing_value")
- }
- }
- } else {
- if ($null -ne $property_value) {
- [void]$diff_list.Add("+$com_name=$property_value")
- }
-
- if ($null -ne $existing_value) {
- [void]$diff_list.Add("-$com_name=$existing_value")
- }
- }
- }
- }
-
- [void]$changes.Add("$property_name[$i] = {`n $($diff_list -join ",`n ")`n}")
- } else {
- # compare the properties of existing and new
- $diff_list = [System.Collections.ArrayList]@()
-
- foreach ($property_arg in $total_args) {
- $com_name = Convert-SnakeToPascalCase -snake $property_arg
- $property_value = $new_property.$property_arg
- $existing_value = $existing_property.$com_name
-
- if ($property_value -is [Hashtable]) {
- foreach ($kv in $property_value.GetEnumerator()) {
- $sub_property_value = $kv.Value
-
- if ($null -ne $sub_property_value) {
- $sub_com_name = Convert-SnakeToPascalCase -snake $kv.Key
- $sub_existing_value = $existing_property.$com_name.$sub_com_name
-
- if ($sub_property_value -cne $sub_existing_value) {
- [void]$diff_list.Add("-$com_name.$sub_com_name=$sub_existing_value")
- [void]$diff_list.Add("+$com_name.$sub_com_name=$sub_property_value")
- }
- }
- }
- } elseif ($null -ne $property_value -and $property_value -cne $existing_value) {
- [void]$diff_list.Add("-$com_name=$existing_value")
- [void]$diff_list.Add("+$com_name=$property_value")
- }
- }
-
- if ($diff_list.Count -gt 0) {
- [void]$changes.Add("$property_name[$i] = {`n $($diff_list -join ",`n ")`n}")
- }
- }
-
- # finally rebuild the new property collection
- $new_object = $collection.Create($type)
- foreach ($property_arg in $total_args) {
- $new_value = $new_property.$property_arg
- if ($new_value -is [Hashtable]) {
- $com_name = Convert-SnakeToPascalCase -snake $property_arg
- $new_object_property = $new_object.$com_name
-
- foreach ($kv in $new_value.GetEnumerator()) {
- $value = $kv.Value
- if ($null -ne $value) {
- Set-PropertyForComObject -com_object $new_object_property -name $property_name -arg $kv.Key -value $value
- }
- }
- } elseif ($null -ne $new_value) {
- Set-PropertyForComObject -com_object $new_object -name $property_name -arg $property_arg -value $new_value
- }
- }
- }
-
- # if there were any extra properties not in the new list, create diff str
- if ($existing_count -gt $new_count) {
- for ($i = $new_count; $i -lt $existing_count; $i++) {
- $diff_list = [System.Collections.ArrayList]@()
- $existing_property = $existing[$i]
- $existing_type = [Enum]::ToObject($enum, $existing_property.Type)
-
- if ($map.ContainsKey($existing_type)) {
- $property_map = $map.$existing_type
- $property_args = $property_map.mandatory + $property_map.optional
-
- foreach ($property_arg in $property_args) {
- $com_name = Convert-SnakeToPascalCase -snake $property_arg
- $existing_value = $existing_property.$com_name
- if ($null -ne $existing_value) {
- [void]$diff_list.Add("-$com_name=$existing_value")
- }
- }
- } else {
- [void]$diff_list.Add("-UNKNOWN TYPE $existing_type")
- }
-
- [void]$changes.Add("-$property_name[$i] = {`n $($diff_list -join ",`n ")`n-}")
- }
- }
-
- return ,$changes
-}
-
-Function Compare-Actions($task_definition) {
- # compares the Actions property and returns a list of list of changed
- # actions for use in a diff string
- # ActionCollection - https://msdn.microsoft.com/en-us/library/windows/desktop/aa446804(v=vs.85).aspx
- # Action - https://msdn.microsoft.com/en-us/library/windows/desktop/aa446803(v=vs.85).aspx
- if ($null -eq $actions) {
- return ,[System.Collections.ArrayList]@()
- }
-
- $task_actions = $task_definition.Actions
- $existing_count = $task_actions.Count
-
- # because we clear the actions and re-add them to keep the order, we need
- # to convert the existing actions to a new list.
- # The Item property in actions starts at 1
- $existing_actions = [System.Collections.ArrayList]@()
- for ($i = 1; $i -le $existing_count; $i++) {
- [void]$existing_actions.Add($task_actions.Item($i))
- }
- if ($existing_count -gt 0) {
- $task_actions.Clear()
- }
-
- $map = @{
- [TASK_ACTION_TYPE]::TASK_ACTION_EXEC = @{
- mandatory = @('path')
- optional = @('arguments', 'working_directory')
- }
- }
- $changes = Compare-PropertyList -collection $task_actions -property_name "action" -new $actions -existing $existing_actions -map $map -enum TASK_ACTION_TYPE
-
- return ,$changes
-}
-
-Function Compare-Principal($task_definition, $task_definition_xml) {
- # compares the Principal property and returns a list of changed objects for
- # use in a diff string
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa382071(v=vs.85).aspx
- $principal_map = @{
- DisplayName = $display_name
- LogonType = $logon_type
- RunLevel = $run_level
- }
- $enum_map = @{
- LogonType = "TASK_LOGON_TYPE"
- RunLevel = "TASK_RUN_LEVEL"
- }
- $task_principal = $task_definition.Principal
- $changes = Compare-Properties -property_name "Principal" -parent_property $task_principal -map $principal_map -enum_map $enum_map
-
- # Principal.UserId and GroupId only returns the username portion of the
- # username, skipping the domain or server name. This makes the
- # comparison process useless so we need to parse the task XML to get
- # the actual sid/username. Depending on OS version this could be the SID
- # or it could be the username, we need to handle that accordingly
- $principal_username_sid = $task_definition_xml.Task.Principals.Principal.UserId
- if ($null -ne $principal_username_sid -and $principal_username_sid -notmatch "^S-\d-\d+(-\d+){1,14}(-\d+){0,1}$") {
- $principal_username_sid = Convert-ToSID -account_name $principal_username_sid
- }
- $principal_group_sid = $task_definition_xml.Task.Principals.Principal.GroupId
- if ($null -ne $principal_group_sid -and $principal_group_sid -notmatch "^S-\d-\d+(-\d+){1,14}(-\d+){0,1}$") {
- $principal_group_sid = Convert-ToSID -account_name $principal_group_sid
- }
-
- if ($null -ne $username_sid) {
- $new_user_name = Convert-FromSid -sid $username_sid
- if ($null -ne $principal_group_sid) {
- $existing_account_name = Convert-FromSid -sid $principal_group_sid
- [void]$changes.Add("-GroupId=$existing_account_name`n+UserId=$new_user_name")
- $task_principal.UserId = $new_user_name
- $task_principal.GroupId = $null
- } elseif ($null -eq $principal_username_sid) {
- [void]$changes.Add("+UserId=$new_user_name")
- $task_principal.UserId = $new_user_name
- } elseif ($principal_username_sid -ne $username_sid) {
- $existing_account_name = Convert-FromSid -sid $principal_username_sid
- [void]$changes.Add("-UserId=$existing_account_name`n+UserId=$new_user_name")
- $task_principal.UserId = $new_user_name
- }
- }
- if ($null -ne $group_sid) {
- $new_group_name = Convert-FromSid -sid $group_sid
- if ($null -ne $principal_username_sid) {
- $existing_account_name = Convert-FromSid -sid $principal_username_sid
- [void]$changes.Add("-UserId=$existing_account_name`n+GroupId=$new_group_name")
- $task_principal.UserId = $null
- $task_principal.GroupId = $new_group_name
- } elseif ($null -eq $principal_group_sid) {
- [void]$changes.Add("+GroupId=$new_group_name")
- $task_principal.GroupId = $new_group_name
- } elseif ($principal_group_sid -ne $group_sid) {
- $existing_account_name = Convert-FromSid -sid $principal_group_sid
- [void]$changes.Add("-GroupId=$existing_account_name`n+GroupId=$new_group_name")
- $task_principal.GroupId = $new_group_name
- }
- }
-
- return ,$changes
-}
-
-Function Compare-RegistrationInfo($task_definition) {
- # compares the RegistrationInfo property and returns a list of changed
- # objects for use in a diff string
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa382100(v=vs.85).aspx
- $reg_info_map = @{
- Author = $author
- Date = $date
- Description = $description
- Source = $source
- Version = $version
- }
- $changes = Compare-Properties -property_name "RegistrationInfo" -parent_property $task_definition.RegistrationInfo -map $reg_info_map
-
- return ,$changes
-}
-
-Function Compare-Settings($task_definition) {
- # compares the task Settings property and returns a list of changed objects
- # for use in a diff string
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383480(v=vs.85).aspx
- $settings_map = @{
- AllowDemandStart = $allow_demand_start
- AllowHardTerminate = $allow_hard_terminate
- Compatibility = $compatibility
- DeleteExpiredTaskAfter = $delete_expired_task_after
- DisallowStartIfOnBatteries = $disallow_start_if_on_batteries
- ExecutionTimeLimit = $execution_time_limit
- Enabled = $enabled
- Hidden = $hidden
- # IdleSettings = $idle_settings # TODO: this takes in a COM object
- MultipleInstances = $multiple_instances
- # NetworkSettings = $network_settings # TODO: this takes in a COM object
- Priority = $priority
- RestartCount = $restart_count
- RestartInterval = $restart_interval
- RunOnlyIfIdle = $run_only_if_idle
- RunOnlyIfNetworkAvailable = $run_only_if_network_available
- StartWhenAvailable = $start_when_available
- StopIfGoingOnBatteries = $stop_if_going_on_batteries
- WakeToRun = $wake_to_run
- }
- $changes = Compare-Properties -property_name "Settings" -parent_property $task_definition.Settings -map $settings_map
-
- return ,$changes
-}
-
-Function Compare-Triggers($task_definition) {
- # compares the task Triggers property and returns a list of changed objects
- # for use in a diff string
- # TriggerCollection - https://msdn.microsoft.com/en-us/library/windows/desktop/aa383875(v=vs.85).aspx
- # Trigger - https://msdn.microsoft.com/en-us/library/windows/desktop/aa383868(v=vs.85).aspx
- if ($null -eq $triggers) {
- return ,[System.Collections.ArrayList]@()
- }
-
- $task_triggers = $task_definition.Triggers
- $existing_count = $task_triggers.Count
-
- # because we clear the actions and re-add them to keep the order, we need
- # to convert the existing actions to a new list.
- # The Item property in actions starts at 1
- $existing_triggers = [System.Collections.ArrayList]@()
- for ($i = 1; $i -le $existing_count; $i++) {
- [void]$existing_triggers.Add($task_triggers.Item($i))
- }
- if ($existing_count -gt 0) {
- $task_triggers.Clear()
- }
-
- $map = @{
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_BOOT = @{
- mandatory = @()
- optional = @('delay', 'enabled', 'end_boundary', 'execution_time_limit', 'start_boundary', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_DAILY = @{
- mandatory = @('start_boundary')
- optional = @('days_interval', 'enabled', 'end_boundary', 'execution_time_limit', 'random_delay', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_EVENT = @{
- mandatory = @('subscription')
- # TODO: ValueQueries is a COM object
- optional = @('delay', 'enabled', 'end_boundary', 'execution_time_limit', 'start_boundary', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_IDLE = @{
- mandatory = @()
- optional = @('enabled', 'end_boundary', 'execution_time_limit', 'start_boundary', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_LOGON = @{
- mandatory = @()
- optional = @('delay', 'enabled', 'end_boundary', 'execution_time_limit', 'start_boundary', 'user_id', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_MONTHLYDOW = @{
- mandatory = @('start_boundary')
- optional = @('days_of_week', 'enabled', 'end_boundary', 'execution_time_limit', 'months_of_year', 'random_delay', 'run_on_last_week_of_month', 'weeks_of_month', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_MONTHLY = @{
- mandatory = @('days_of_month', 'start_boundary')
- optional = @('enabled', 'end_boundary', 'execution_time_limit', 'months_of_year', 'random_delay', 'run_on_last_day_of_month', 'start_boundary', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_REGISTRATION = @{
- mandatory = @()
- optional = @('delay', 'enabled', 'end_boundary', 'execution_time_limit', 'start_boundary', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_TIME = @{
- mandatory = @('start_boundary')
- optional = @('enabled', 'end_boundary', 'execution_time_limit', 'random_delay', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_WEEKLY = @{
- mandatory = @('days_of_week', 'start_boundary')
- optional = @('enabled', 'end_boundary', 'execution_time_limit', 'random_delay', 'weeks_interval', 'repetition')
- }
- [TASK_TRIGGER_TYPE2]::TASK_TRIGGER_SESSION_STATE_CHANGE = @{
- mandatory = @('days_of_week', 'start_boundary')
- optional = @('delay', 'enabled', 'end_boundary', 'execution_time_limit', 'state_change', 'user_id', 'repetition')
- }
- }
- $changes = Compare-PropertyList -collection $task_triggers -property_name "trigger" -new $triggers -existing $existing_triggers -map $map -enum TASK_TRIGGER_TYPE2
-
- return ,$changes
-}
-
-Function Test-TaskExists($task_folder, $name) {
- # checks if a task exists in the TaskFolder COM object, returns null if the
- # task does not exist, otherwise returns the RegisteredTask object
- $task = $null
- if ($task_folder) {
- $raw_tasks = $task_folder.GetTasks(1) # 1 = TASK_ENUM_HIDDEN
-
- for ($i = 1; $i -le $raw_tasks.Count; $i++) {
- if ($raw_tasks.Item($i).Name -eq $name) {
- $task = $raw_tasks.Item($i)
- break
- }
- }
- }
-
- return $task
-}
-
-Function Test-XmlDurationFormat($key, $value) {
- # validate value is in the Duration Data Type format
- # PnYnMnDTnHnMnS
- try {
- $time_span = [System.Xml.XmlConvert]::ToTimeSpan($value)
- return $time_span
- } catch [System.FormatException] {
- Fail-Json -obj $result -message "trigger option '$key' must be in the XML duration format but was '$value'"
- }
-}
-
-######################################
-### VALIDATION/BUILDING OF OPTIONS ###
-######################################
-# convert username and group to SID if set
-$username_sid = $null
-if ($username) {
- $username_sid = Convert-ToSID -account_name $username
-}
-$group_sid = $null
-if ($group) {
- $group_sid = Convert-ToSID -account_name $group
-}
-
-# validate store_password and logon_type
-if ($null -ne $logon_type) {
- $full_enum_name = "TASK_LOGON_$($logon_type.ToUpper())"
- $logon_type = [TASK_LOGON_TYPE]::$full_enum_name
-}
-
-# now validate the logon_type option with the other parameters
-if ($null -ne $username -and $null -ne $group) {
- Fail-Json -obj $result -message "username and group can not be set at the same time"
-}
-if ($null -ne $logon_type) {
- if ($logon_type -eq [TASK_LOGON_TYPE]::TASK_LOGON_S4U -and $null -eq $password) {
- Fail-Json -obj $result -message "password must be set when logon_type=s4u"
- }
-
- if ($logon_type -eq [TASK_LOGON_TYPE]::TASK_LOGON_GROUP -and $null -eq $group) {
- Fail-Json -obj $result -message "group must be set when logon_type=group"
- }
-
- # SIDs == Local System, Local Service and Network Service
- if ($logon_type -eq [TASK_LOGON_TYPE]::TASK_LOGON_SERVICE_ACCOUNT -and $username_sid -notin @("S-1-5-18", "S-1-5-19", "S-1-5-20")) {
- Fail-Json -obj $result -message "username must be SYSTEM, LOCAL SERVICE or NETWORK SERVICE when logon_type=service_account"
- }
-}
-
-# convert the run_level to enum value
-if ($null -ne $run_level) {
- if ($run_level -eq "limited") {
- $run_level = [TASK_RUN_LEVEL]::TASK_RUNLEVEL_LUA
- } else {
- $run_level = [TASK_RUN_LEVEL]::TASK_RUNLEVEL_HIGHEST
- }
-}
-
-# manually add the only support action type for each action - also convert PSCustomObject to Hashtable
-for ($i = 0; $i -lt $actions.Count; $i++) {
- $action = $actions[$i]
- $action.type = [TASK_ACTION_TYPE]::TASK_ACTION_EXEC
- if (-not $action.ContainsKey("path")) {
- Fail-Json -obj $result -message "action entry must contain the key 'path'"
- }
- $actions[$i] = $action
-}
-
-# convert and validate the triggers - and convert PSCustomObject to Hashtable
-for ($i = 0; $i -lt $triggers.Count; $i++) {
- $trigger = $triggers[$i]
- $valid_trigger_types = @('event', 'time', 'daily', 'weekly', 'monthly', 'monthlydow', 'idle', 'registration', 'boot', 'logon', 'session_state_change')
- if (-not $trigger.ContainsKey("type")) {
- Fail-Json -obj $result -message "a trigger entry must contain a key 'type' with a value of '$($valid_trigger_types -join "', '")'"
- }
-
- $trigger_type = $trigger.type
- if ($trigger_type -notin $valid_trigger_types) {
- Fail-Json -obj $result -message "the specified trigger type '$trigger_type' is not valid, type must be a value of '$($valid_trigger_types -join "', '")'"
- }
-
- $full_enum_name = "TASK_TRIGGER_$($trigger_type.ToUpper())"
- $trigger_type = [TASK_TRIGGER_TYPE2]::$full_enum_name
- $trigger.type = $trigger_type
-
- $date_properties = @('start_boundary', 'end_boundary')
- foreach ($property_name in $date_properties) {
- # validate the date is in the DateTime format
- # yyyy-mm-ddThh:mm:ss
- if ($trigger.ContainsKey($property_name)) {
- $date_value = $trigger.$property_name
- try {
- $date = Get-Date -Date $date_value -Format "yyyy-MM-dd'T'HH:mm:ssK"
- # make sure we convert it to the full string format
- $trigger.$property_name = $date.ToString()
- } catch [System.Management.Automation.ParameterBindingException] {
- Fail-Json -obj $result -message "trigger option '$property_name' must be in the format 'YYYY-MM-DDThh:mm:ss' format but was '$date_value'"
- }
- }
- }
-
- $time_properties = @('execution_time_limit', 'delay', 'random_delay')
- foreach ($property_name in $time_properties) {
- if ($trigger.ContainsKey($property_name)) {
- $time_span = $trigger.$property_name
- Test-XmlDurationFormat -key $property_name -value $time_span
- }
- }
-
- if ($trigger.ContainsKey("repetition")) {
- if ($trigger.repetition -is [Array]) {
- Add-DeprecationWarning -obj $result -message "repetition is a list, should be defined as a dict" -version "2.12"
- $trigger.repetition = $trigger.repetition[0]
- }
-
- $interval_timespan = $null
- if ($trigger.repetition.ContainsKey("interval") -and $null -ne $trigger.repetition.interval) {
- $interval_timespan = Test-XmlDurationFormat -key "interval" -value $trigger.repetition.interval
- }
-
- $duration_timespan = $null
- if ($trigger.repetition.ContainsKey("duration") -and $null -ne $trigger.repetition.duration) {
- $duration_timespan = Test-XmlDurationFormat -key "duration" -value $trigger.repetition.duration
- }
-
- if ($null -ne $interval_timespan -and $null -ne $duration_timespan -and $interval_timespan -gt $duration_timespan) {
- Fail-Json -obj $result -message "trigger repetition option 'interval' value '$($trigger.repetition.interval)' must be less than or equal to 'duration' value '$($trigger.repetition.duration)'"
- }
- }
-
- # convert out human readble text to the hex values for these properties
- if ($trigger.ContainsKey("days_of_week")) {
- $days = $trigger.days_of_week
- if ($days -is [String]) {
- $days = $days.Split(",").Trim()
- } elseif ($days -isnot [Array]) {
- $days = @($days)
- }
-
- $day_value = 0
- foreach ($day in $days) {
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa382057(v=vs.85).aspx
- switch ($day) {
- sunday { $day_value = $day_value -bor 0x01 }
- monday { $day_value = $day_value -bor 0x02 }
- tuesday { $day_value = $day_value -bor 0x04 }
- wednesday { $day_value = $day_value -bor 0x08 }
- thursday { $day_value = $day_value -bor 0x10 }
- friday { $day_value = $day_value -bor 0x20 }
- saturday { $day_value = $day_value -bor 0x40 }
- default { Fail-Json -obj $result -message "invalid day of week '$day', check the spelling matches the full day name" }
- }
- }
- if ($day_value -eq 0) {
- $day_value = $null
- }
-
- $trigger.days_of_week = $day_value
- }
- if ($trigger.ContainsKey("days_of_month")) {
- $days = $trigger.days_of_month
- if ($days -is [String]) {
- $days = $days.Split(",").Trim()
- } elseif ($days -isnot [Array]) {
- $days = @($days)
- }
-
- $day_value = 0
- foreach ($day in $days) {
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa382063(v=vs.85).aspx
- switch ($day) {
- 1 { $day_value = $day_value -bor 0x01 }
- 2 { $day_value = $day_value -bor 0x02 }
- 3 { $day_value = $day_value -bor 0x04 }
- 4 { $day_value = $day_value -bor 0x08 }
- 5 { $day_value = $day_value -bor 0x10 }
- 6 { $day_value = $day_value -bor 0x20 }
- 7 { $day_value = $day_value -bor 0x40 }
- 8 { $day_value = $day_value -bor 0x80 }
- 9 { $day_value = $day_value -bor 0x100 }
- 10 { $day_value = $day_value -bor 0x200 }
- 11 { $day_value = $day_value -bor 0x400 }
- 12 { $day_value = $day_value -bor 0x800 }
- 13 { $day_value = $day_value -bor 0x1000 }
- 14 { $day_value = $day_value -bor 0x2000 }
- 15 { $day_value = $day_value -bor 0x4000 }
- 16 { $day_value = $day_value -bor 0x8000 }
- 17 { $day_value = $day_value -bor 0x10000 }
- 18 { $day_value = $day_value -bor 0x20000 }
- 19 { $day_value = $day_value -bor 0x40000 }
- 20 { $day_value = $day_value -bor 0x80000 }
- 21 { $day_value = $day_value -bor 0x100000 }
- 22 { $day_value = $day_value -bor 0x200000 }
- 23 { $day_value = $day_value -bor 0x400000 }
- 24 { $day_value = $day_value -bor 0x800000 }
- 25 { $day_value = $day_value -bor 0x1000000 }
- 26 { $day_value = $day_value -bor 0x2000000 }
- 27 { $day_value = $day_value -bor 0x4000000 }
- 28 { $day_value = $day_value -bor 0x8000000 }
- 29 { $day_value = $day_value -bor 0x10000000 }
- 30 { $day_value = $day_value -bor 0x20000000 }
- 31 { $day_value = $day_value -bor 0x40000000 }
- default { Fail-Json -obj $result -message "invalid day of month '$day', please specify numbers from 1-31" }
- }
- }
- if ($day_value -eq 0) {
- $day_value = $null
- }
- $trigger.days_of_month = $day_value
- }
- if ($trigger.ContainsKey("weeks_of_month")) {
- $weeks = $trigger.weeks_of_month
- if ($weeks -is [String]) {
- $weeks = $weeks.Split(",").Trim()
- } elseif ($weeks -isnot [Array]) {
- $weeks = @($weeks)
- }
-
- $week_value = 0
- foreach ($week in $weeks) {
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa382061(v=vs.85).aspx
- switch ($week) {
- 1 { $week_value = $week_value -bor 0x01 }
- 2 { $week_value = $week_value -bor 0x02 }
- 3 { $week_value = $week_value -bor 0x04 }
- 4 { $week_value = $week_value -bor 0x08 }
- default { Fail-Json -obj $result -message "invalid week of month '$week', please specify weeks from 1-4" }
- }
-
- }
- if ($week_value -eq 0) {
- $week_value = $null
- }
- $trigger.weeks_of_month = $week_value
- }
- if ($trigger.ContainsKey("months_of_year")) {
- $months = $trigger.months_of_year
- if ($months -is [String]) {
- $months = $months.Split(",").Trim()
- } elseif ($months -isnot [Array]) {
- $months = @($months)
- }
-
- $month_value = 0
- foreach ($month in $months) {
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa382064(v=vs.85).aspx
- switch ($month) {
- january { $month_value = $month_value -bor 0x01 }
- february { $month_value = $month_value -bor 0x02 }
- march { $month_value = $month_value -bor 0x04 }
- april { $month_value = $month_value -bor 0x08 }
- may { $month_value = $month_value -bor 0x10 }
- june { $month_value = $month_value -bor 0x20 }
- july { $month_value = $month_value -bor 0x40 }
- august { $month_value = $month_value -bor 0x80 }
- september { $month_value = $month_value -bor 0x100 }
- october { $month_value = $month_value -bor 0x200 }
- november { $month_value = $month_value -bor 0x400 }
- december { $month_value = $month_value -bor 0x800 }
- default { Fail-Json -obj $result -message "invalid month name '$month', please specify full month name" }
- }
- }
- if ($month_value -eq 0) {
- $month_value = $null
- }
- $trigger.months_of_year = $month_value
- }
- $triggers[$i] = $trigger
-}
-
-# add \ to start of path if it is not already there
-if (-not $path.StartsWith("\")) {
- $path = "\$path"
-}
-# ensure path does not end with \ if more than 1 char
-if ($path.EndsWith("\") -and $path.Length -ne 1) {
- $path = $path.Substring(0, $path.Length - 1)
-}
-
-########################
-### START CODE BLOCK ###
-########################
-$service = New-Object -ComObject Schedule.Service
-try {
- $service.Connect()
-} catch {
- Fail-Json -obj $result -message "failed to connect to the task scheduler service: $($_.Exception.Message)"
-}
-
-# check that the path for the task set exists, create if need be
-try {
- $task_folder = $service.GetFolder($path)
-} catch {
- $task_folder = $null
-}
-
-# try and get the task at the path
-$task = Test-TaskExists -task_folder $task_folder -name $name
-$task_path = Join-Path -Path $path -ChildPath $name
-
-if ($state -eq "absent") {
- if ($null -ne $task) {
- if (-not $check_mode) {
- try {
- $task_folder.DeleteTask($name, 0)
- } catch {
- Fail-Json -obj $result -message "failed to delete task '$name' at path '$path': $($_.Exception.Message)"
- }
- }
- if ($diff_mode) {
- $result.diff.prepared = "-[Task]`n-$task_path`n"
- }
- $result.changed = $true
-
- # check if current folder has any more tasks
- $other_tasks = $task_folder.GetTasks(1) # 1 = TASK_ENUM_HIDDEN
- if ($other_tasks.Count -eq 0 -and $task_folder.Name -ne "\") {
- try {
- $task_folder.DeleteFolder($null, $null)
- } catch {
- Fail-Json -obj $result -message "failed to delete empty task folder '$path' after task deletion: $($_.Exception.Message)"
- }
- }
- }
-} else {
- if ($null -eq $task) {
- $create_diff_string = "+[Task]`n+$task_path`n`n"
- # to create a bare minimum task we need 1 action
- if ($null -eq $actions -or $actions.Count -eq 0) {
- Fail-Json -obj $result -message "cannot create a task with no actions, set at least one action with a path to an executable"
- }
-
- # Create a bare minimum task here, further properties will be set later on
- $task_definition = $service.NewTask(0)
-
- # Set Actions info
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa446803(v=vs.85).aspx
- $create_diff_string += "[Actions]`n"
- $task_actions = $task_definition.Actions
- foreach ($action in $actions) {
- $create_diff_string += "+action[0] = {`n +Type=$([TASK_ACTION_TYPE]::TASK_ACTION_EXEC),`n +Path=$($action.path)`n"
- $task_action = $task_actions.Create([TASK_ACTION_TYPE]::TASK_ACTION_EXEC)
- $task_action.Path = $action.path
- if ($null -ne $action.arguments) {
- $create_diff_string += " +Arguments=$($action.arguments)`n"
- $task_action.Arguments = $action.arguments
- }
- if ($null -ne $action.working_directory) {
- $create_diff_string += " +WorkingDirectory=$($action.working_directory)`n"
- $task_action.WorkingDirectory = $action.working_directory
- }
- $create_diff_string += "+}`n"
- }
-
- # Register the new task
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa382577(v=vs.85).aspx
- if ($check_mode) {
- # Only validate the task in check mode
- $task_creation_flags = [TASK_CREATION]::TASK_VALIDATE_ONLY
- } else {
- # Create the task but do not fire it as we still need to configure it further below
- $task_creation_flags = [TASK_CREATION]::TASK_CREATE -bor [TASK_CREATION]::TASK_IGNORE_REGISTRATION_TRIGGERS
- }
-
- # folder doesn't exist, need to create
- if ($null -eq $task_folder) {
- $task_folder = $service.GetFolder("\")
- try {
- if (-not $check_mode) {
- $task_folder = $task_folder.CreateFolder($path)
- }
- } catch {
- Fail-Json -obj $result -message "failed to create new folder at path '$path': $($_.Exception.Message)"
- }
- }
-
- try {
- $task = $task_folder.RegisterTaskDefinition($name, $task_definition, $task_creation_flags, $null, $null, $null)
- } catch {
- Fail-Json -obj $result -message "failed to register new task definition: $($_.Exception.Message)"
- }
- if ($diff_mode) {
- $result.diff.prepared = $create_diff_string
- }
-
- $result.changed = $true
- }
-
- # we cannot configure a task that was created above in check mode as it
- # won't actually exist
- if ($task) {
- $task_definition = $task.Definition
- $task_definition_xml = [xml]$task_definition.XmlText
-
- $action_changes = Compare-Actions -task_definition $task_definition
- $principal_changed = Compare-Principal -task_definition $task_definition -task_definition_xml $task_definition_xml
- $reg_info_changed = Compare-RegistrationInfo -task_definition $task_definition
- $settings_changed = Compare-Settings -task_definition $task_definition
- $trigger_changes = Compare-Triggers -task_definition $task_definition
-
- # compile the diffs into one list with headers
- $task_diff = [System.Collections.ArrayList]@()
- if ($action_changes.Count -gt 0) {
- [void]$task_diff.Add("[Actions]")
- foreach ($action_change in $action_changes) {
- [void]$task_diff.Add($action_change)
- }
- [void]$task_diff.Add("`n")
- }
- if ($principal_changed.Count -gt 0) {
- [void]$task_diff.Add("[Principal]")
- foreach ($principal_change in $principal_changed) {
- [void]$task_diff.Add($principal_change)
- }
- [void]$task_diff.Add("`n")
- }
- if ($reg_info_changed.Count -gt 0) {
- [void]$task_diff.Add("[Registration Info]")
- foreach ($reg_info_change in $reg_info_changed) {
- [void]$task_diff.Add($reg_info_change)
- }
- [void]$task_diff.Add("`n")
- }
- if ($settings_changed.Count -gt 0) {
- [void]$task_diff.Add("[Settings]")
- foreach ($settings_change in $settings_changed) {
- [void]$task_diff.add($settings_change)
- }
- [void]$task_diff.Add("`n")
- }
- if ($trigger_changes.Count -gt 0) {
- [void]$task_diff.Add("[Triggers]")
- foreach ($trigger_change in $trigger_changes) {
- [void]$task_diff.Add("$trigger_change")
- }
- [void]$task_diff.Add("`n")
- }
-
- if ($null -ne $password -and (($update_password -eq $true) -or ($task_diff.Count -gt 0))) {
- # because we can't compare the passwords we just need to reset it
- $register_username = $username
- $register_password = $password
- $register_logon_type = $task_principal.LogonType
- } else {
- # will inherit from the Principal property values
- $register_username = $null
- $register_password = $null
- $register_logon_type = $null
- }
-
- if ($task_diff.Count -gt 0 -or $null -ne $register_password) {
- if ($check_mode) {
- # Only validate the task in check mode
- $task_creation_flags = [TASK_CREATION]::TASK_VALIDATE_ONLY
- } else {
- # Create the task
- $task_creation_flags = [TASK_CREATION]::TASK_CREATE_OR_UPDATE
- }
- try {
- $task_folder.RegisterTaskDefinition($name, $task_definition, $task_creation_flags, $register_username, $register_password, $register_logon_type) | Out-Null
- } catch {
- Fail-Json -obj $result -message "failed to modify scheduled task: $($_.Exception.Message)"
- }
-
- $result.changed = $true
-
- if ($diff_mode) {
- $changed_diff_text = $task_diff -join "`n"
- if ($null -ne $result.diff.prepared) {
- $diff_text = "$($result.diff.prepared)`n$changed_diff_text"
- } else {
- $diff_text = $changed_diff_text
- }
- $result.diff.prepared = $diff_text.Trim()
- }
- }
- }
-}
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_scheduled_task.py b/lib/ansible/modules/windows/win_scheduled_task.py
deleted file mode 100644
index 6e64738451..0000000000
--- a/lib/ansible/modules/windows/win_scheduled_task.py
+++ /dev/null
@@ -1,546 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_scheduled_task
-version_added: "2.0"
-short_description: Manage scheduled tasks
-description:
-- Creates/modified or removes Windows scheduled tasks.
-options:
- # module definition options
- name:
- description:
- - The name of the scheduled task without the path.
- type: str
- required: yes
- path:
- description:
- - Task folder in which this task will be stored.
- - Will create the folder when C(state=present) and the folder does not
- already exist.
- - Will remove the folder when C(state=absent) and there are no tasks left
- in the folder.
- type: str
- default: \
- state:
- description:
- - When C(state=present) will ensure the task exists.
- - When C(state=absent) will ensure the task does not exist.
- type: str
- choices: [ absent, present ]
- default: present
-
- # Action options
- actions:
- description:
- - A list of action to configure for the task.
- - See suboptions for details on how to construct each list entry.
- - When creating a task there MUST be at least one action but when deleting
- a task this can be a null or an empty list.
- - The ordering of this list is important, the module will ensure the order
- is kept when modifying the task.
- - This module only supports the C(ExecAction) type but can still delete the
- older legacy types.
- type: list
- suboptions:
- path:
- description:
- - The path to the executable for the ExecAction.
- type: str
- required: yes
- arguments:
- description:
- - An argument string to supply for the executable.
- type: str
- working_directory:
- description:
- - The working directory to run the executable from.
- type: str
- version_added: '2.5'
-
- # Trigger options
- triggers:
- description:
- - A list of triggers to configure for the task.
- - See suboptions for details on how to construct each list entry.
- - The ordering of this list is important, the module will ensure the order
- is kept when modifying the task.
- - There are multiple types of triggers, see U(https://msdn.microsoft.com/en-us/library/windows/desktop/aa383868.aspx)
- for a list of trigger types and their options.
- - The suboption options listed below are not required for all trigger
- types, read the description for more details.
- type: list
- suboptions:
- type:
- description:
- - The trigger type, this value controls what below options are
- required.
- type: str
- required: yes
- choices: [ boot, daily, event, idle, logon, monthlydow, monthly, registration, time, weekly, session_state_change ]
- enabled:
- description:
- - Whether to set the trigger to enabled or disabled
- - Used in all trigger types.
- type: bool
- start_boundary:
- description:
- - The start time for the task, even if the trigger meets the other
- start criteria, it won't start until this time is met.
- - If you wish to run a task at 9am on a day you still need to specify
- the date on which the trigger is activated, you can set any date even
- ones in the past.
- - Required when C(type) is C(daily), C(monthlydow), C(monthly),
- C(time), C(weekly), (session_state_change).
- - Optional for the rest of the trigger types.
- - This is in ISO 8601 DateTime format C(YYYY-MM-DDThh:mm:ss).
- type: str
- end_boundary:
- description:
- - The end time for when the trigger is deactivated.
- - This is in ISO 8601 DateTime format C(YYYY-MM-DDThh:mm:ss).
- type: str
- execution_time_limit:
- description:
- - The maximum amount of time that the task is allowed to run for.
- - Optional for all the trigger types.
- - Is in the ISO 8601 Duration format C(P[n]Y[n]M[n]DT[n]H[n]M[n]S).
- type: str
- delay:
- description:
- - The time to delay the task from running once the trigger has been
- fired.
- - Optional when C(type) is C(boot), C(event), C(logon),
- C(registration), C(session_state_change).
- - Is in the ISO 8601 Duration format C(P[n]Y[n]M[n]DT[n]H[n]M[n]S).
- type: str
- random_delay:
- description:
- - The delay time that is randomly added to the start time of the
- trigger.
- - Optional when C(type) is C(daily), C(monthlydow), C(monthly),
- C(time), C(weekly).
- - Is in the ISO 8601 Duration format C(P[n]Y[n]M[n]DT[n]H[n]M[n]S).
- type: str
- subscription:
- description:
- - Only used and is required for C(type=event).
- - The XML query string that identifies the event that fires the
- trigger.
- type: str
- user_id:
- description:
- - The username that the trigger will target.
- - Optional when C(type) is C(logon), C(session_state_change).
- - Can be the username or SID of a user.
- - When C(type=logon) and you want the trigger to fire when a user in a
- group logs on, leave this as null and set C(group) to the group you
- wish to trigger.
- type: str
- days_of_week:
- description:
- - The days of the week for the trigger.
- - Can be a list or comma separated string of full day names e.g. monday
- instead of mon.
- - Required when C(type) is C(weekly), C(type=session_state_change).
- - Optional when C(type=monthlydow).
- type: str
- days_of_month:
- description:
- - The days of the month from 1 to 31 for the triggers.
- - If you wish to set the trigger for the last day of any month
- use C(run_on_last_day_of_month).
- - Can be a list or comma separated string of day numbers.
- - Required when C(type=monthly).
- type: str
- weeks_of_month:
- description:
- - The weeks of the month for the trigger.
- - Can be a list or comma separated string of the numbers 1 to 4
- representing the first to 4th week of the month.
- - Optional when C(type=monthlydow).
- type: str
- months_of_year:
- description:
- - The months of the year for the trigger.
- - Can be a list or comma separated string of full month names e.g.
- march instead of mar.
- - Optional when C(type) is C(monthlydow), C(monthly).
- type: str
- run_on_last_week_of_month:
- description:
- - Boolean value that sets whether the task runs on the last week of the
- month.
- - Optional when C(type) is C(monthlydow).
- type: bool
- run_on_last_day_of_month:
- description:
- - Boolean value that sets whether the task runs on the last day of the
- month.
- - Optional when C(type) is C(monthly).
- type: bool
- weeks_interval:
- description:
- - The interval of weeks to run on, e.g. C(1) means every week while
- C(2) means every other week.
- - Optional when C(type=weekly).
- type: int
- repetition:
- description:
- - Allows you to define the repetition action of the trigger that defines how often the task is run and how long the repetition pattern is repeated
- after the task is started.
- - It takes in the following keys, C(duration), C(interval), C(stop_at_duration_end)
- suboptions:
- duration:
- description:
- - Defines how long the pattern is repeated.
- - The value is in the ISO 8601 Duration format C(P[n]Y[n]M[n]DT[n]H[n]M[n]S).
- - By default this is not set which means it will repeat indefinitely.
- type: str
- interval:
- description:
- - The amount of time between each restart of the task.
- - The value is written in the ISO 8601 Duration format C(P[n]Y[n]M[n]DT[n]H[n]M[n]S).
- type: str
- stop_at_duration_end:
- description:
- - Whether a running instance of the task is stopped at the end of the repetition pattern.
- type: bool
- version_added: '2.5'
-
- # Principal options
- display_name:
- description:
- - The name of the user/group that is displayed in the Task Scheduler UI.
- type: str
- version_added: '2.5'
- group:
- description:
- - The group that will run the task.
- - C(group) and C(username) are exclusive to each other and cannot be set
- at the same time.
- - C(logon_type) can either be not set or equal C(group).
- type: str
- version_added: '2.5'
- logon_type:
- description:
- - The logon method that the task will run with.
- - C(password) means the password will be stored and the task has access
- to network resources.
- - C(s4u) means the existing token will be used to run the task and no
- password will be stored with the task. Means no network or encrypted
- files access.
- - C(interactive_token) means the user must already be logged on
- interactively and will run in an existing interactive session.
- - C(group) means that the task will run as a group.
- - C(service_account) means that a service account like System, Local
- Service or Network Service will run the task.
- type: str
- choices: [ none, password, s4u, interactive_token, group, service_account, token_or_password ]
- version_added: '2.5'
- run_level:
- description:
- - The level of user rights used to run the task.
- - If not specified the task will be created with limited rights.
- type: str
- choices: [ limited, highest ]
- aliases: [ runlevel ]
- version_added: '2.4'
- username:
- description:
- - The user to run the scheduled task as.
- - Will default to the current user under an interactive token if not
- specified during creation.
- - The user account specified must have the C(SeBatchLogonRight) logon right
- which can be added with M(win_user_right).
- type: str
- aliases: [ user ]
- password:
- description:
- - The password for the user account to run the scheduled task as.
- - This is required when running a task without the user being logged in,
- excluding the builtin service accounts and Group Managed Service Accounts (gMSA).
- - If set, will always result in a change unless C(update_password) is set
- to C(no) and no other changes are required for the service.
- type: str
- version_added: '2.4'
- update_password:
- description:
- - Whether to update the password even when not other changes have occurred.
- - When C(yes) will always result in a change when executing the module.
- type: bool
- default: yes
- version_added: '2.5'
-
- # RegistrationInfo options
- author:
- description:
- - The author of the task.
- type: str
- version_added: '2.5'
- date:
- description:
- - The date when the task was registered.
- type: str
- version_added: '2.5'
- description:
- description:
- - The description of the task.
- type: str
- version_added: '2.5'
- source:
- description:
- - The source of the task.
- type: str
- version_added: '2.5'
- version:
- description:
- - The version number of the task.
- type: str
- version_added: '2.5'
-
- # Settings options
- allow_demand_start:
- description:
- - Whether the task can be started by using either the Run command or the
- Context menu.
- type: bool
- version_added: '2.5'
- allow_hard_terminate:
- description:
- - Whether the task can be terminated by using TerminateProcess.
- type: bool
- version_added: '2.5'
- compatibility:
- description:
- - The integer value with indicates which version of Task Scheduler a task
- is compatible with.
- - C(0) means the task is compatible with the AT command.
- - C(1) means the task is compatible with Task Scheduler 1.0.
- - C(2) means the task is compatible with Task Scheduler 2.0.
- type: int
- choices: [ 0, 1, 2 ]
- version_added: '2.5'
- delete_expired_task_after:
- description:
- - The amount of time that the Task Scheduler will wait before deleting the
- task after it expires.
- - A task expires after the end_boundary has been exceeded for all triggers
- associated with the task.
- - This is in the ISO 8601 Duration format C(P[n]Y[n]M[n]DT[n]H[n]M[n]S).
- type: str
- version_added: '2.5'
- disallow_start_if_on_batteries:
- description:
- - Whether the task will not be started if the computer is running on
- battery power.
- type: bool
- version_added: '2.5'
- enabled:
- description:
- - Whether the task is enabled, the task can only run when C(yes).
- type: bool
- version_added: '2.5'
- execution_time_limit:
- description:
- - The amount of time allowed to complete the task.
- - When set to `PT0S`, the time limit is infinite.
- - When omitted, the default time limit is 72 hours.
- - This is in the ISO 8601 Duration format C(P[n]Y[n]M[n]DT[n]H[n]M[n]S).
- type: str
- version_added: '2.5'
- hidden:
- description:
- - Whether the task will be hidden in the UI.
- type: bool
- version_added: '2.5'
- multiple_instances:
- description:
- - An integer that indicates the behaviour when starting a task that is
- already running.
- - C(0) will start a new instance in parallel with existing instances of
- that task.
- - C(1) will wait until other instances of that task to finish running
- before starting itself.
- - C(2) will not start a new instance if another is running.
- - C(3) will stop other instances of the task and start the new one.
- type: int
- choices: [ 0, 1, 2, 3 ]
- version_added: '2.5'
- priority:
- description:
- - The priority level (0-10) of the task.
- - When creating a new task the default is C(7).
- - See U(https://msdn.microsoft.com/en-us/library/windows/desktop/aa383512.aspx)
- for details on the priority levels.
- type: int
- version_added: '2.5'
- restart_count:
- description:
- - The number of times that the Task Scheduler will attempt to restart the
- task.
- type: int
- version_added: '2.5'
- restart_interval:
- description:
- - How long the Task Scheduler will attempt to restart the task.
- - If this is set then C(restart_count) must also be set.
- - The maximum allowed time is 31 days.
- - The minimum allowed time is 1 minute.
- - This is in the ISO 8601 Duration format C(P[n]Y[n]M[n]DT[n]H[n]M[n]S).
- type: str
- version_added: '2.5'
- run_only_if_idle:
- description:
- - Whether the task will run the task only if the computer is in an idle
- state.
- type: bool
- version_added: '2.5'
- run_only_if_network_available:
- description:
- - Whether the task will run only when a network is available.
- type: bool
- version_added: '2.5'
- start_when_available:
- description:
- - Whether the task can start at any time after its scheduled time has
- passed.
- type: bool
- version_added: '2.5'
- stop_if_going_on_batteries:
- description:
- - Whether the task will be stopped if the computer begins to run on battery
- power.
- type: bool
- version_added: '2.5'
- wake_to_run:
- description:
- - Whether the task will wake the computer when it is time to run the task.
- type: bool
- version_added: '2.5'
-notes:
-- In Ansible 2.4 and earlier, this could only be run on Server 2012/Windows 8
- or newer. Since Ansible 2.5 this restriction has been lifted.
-- The option names and structure for actions and triggers of a service follow
- the C(RegisteredTask) naming standard and requirements, it would be useful to
- read up on this guide if coming across any issues U(https://msdn.microsoft.com/en-us/library/windows/desktop/aa382542.aspx).
-- A Group Managed Service Account (gMSA) can be used by setting C(logon_type) to C(password)
- and omitting the password parameter. For more information on gMSAs,
- see U(https://techcommunity.microsoft.com/t5/Core-Infrastructure-and-Security/Windows-Server-2012-Group-Managed-Service-Accounts/ba-p/255910)
-seealso:
-- module: win_scheduled_task_stat
-- module: win_user_right
-author:
-- Peter Mounce (@petemounce)
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Create a task to open 2 command prompts as SYSTEM
- win_scheduled_task:
- name: TaskName
- description: open command prompt
- actions:
- - path: cmd.exe
- arguments: /c hostname
- - path: cmd.exe
- arguments: /c whoami
- triggers:
- - type: daily
- start_boundary: '2017-10-09T09:00:00'
- username: SYSTEM
- state: present
- enabled: yes
-
-- name: Create task to run a PS script as NETWORK service on boot
- win_scheduled_task:
- name: TaskName2
- description: Run a PowerShell script
- actions:
- - path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
- arguments: -ExecutionPolicy Unrestricted -NonInteractive -File C:\TestDir\Test.ps1
- triggers:
- - type: boot
- username: NETWORK SERVICE
- run_level: highest
- state: present
-
-- name: Update Local Security Policy to allow users to run scheduled tasks
- win_user_right:
- name: SeBatchLogonRight
- users:
- - LocalUser
- - DOMAIN\NetworkUser
- action: add
-
-- name: Change above task to run under a domain user account, storing the passwords
- win_scheduled_task:
- name: TaskName2
- username: DOMAIN\User
- password: Password
- logon_type: password
-
-- name: Change the above task again, choosing not to store the password
- win_scheduled_task:
- name: TaskName2
- username: DOMAIN\User
- logon_type: s4u
-
-- name: Change above task to use a gMSA, where the password is managed automatically
- win_scheduled_task:
- name: TaskName2
- username: DOMAIN\gMsaSvcAcct$
- logon_type: password
-
-- name: Create task with multiple triggers
- win_scheduled_task:
- name: TriggerTask
- path: \Custom
- actions:
- - path: cmd.exe
- triggers:
- - type: daily
- - type: monthlydow
- username: SYSTEM
-
-- name: Set logon type to password but don't force update the password
- win_scheduled_task:
- name: TriggerTask
- path: \Custom
- actions:
- - path: cmd.exe
- username: Administrator
- password: password
- update_password: no
-
-- name: Disable a task that already exists
- win_scheduled_task:
- name: TaskToDisable
- enabled: no
-
-- name: Create a task that will be repeated every minute for five minutes
- win_scheduled_task:
- name: RepeatedTask
- description: open command prompt
- actions:
- - path: cmd.exe
- arguments: /c hostname
- triggers:
- - type: registration
- repetition:
- interval: PT1M
- duration: PT5M
- stop_at_duration_end: yes
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_scheduled_task_stat.ps1 b/lib/ansible/modules/windows/win_scheduled_task_stat.ps1
deleted file mode 100644
index 37bc78a281..0000000000
--- a/lib/ansible/modules/windows/win_scheduled_task_stat.ps1
+++ /dev/null
@@ -1,330 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.CamelConversion
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.SID
-
-$params = Parse-Args -arguments $args
-$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
-
-$path = Get-AnsibleParam -obj $params -name "path" -type "str" -default "\"
-$name = Get-AnsibleParam -obj $params -name "name" -type "str"
-
-$result = @{
- changed = $false
-}
-
-$task_enums = @"
-public enum TASK_ACTION_TYPE
-{
- TASK_ACTION_EXEC = 0,
- // The below are not supported and are only kept for documentation purposes
- TASK_ACTION_COM_HANDLER = 5,
- TASK_ACTION_SEND_EMAIL = 6,
- TASK_ACTION_SHOW_MESSAGE = 7
-}
-
-public enum TASK_LOGON_TYPE
-{
- TASK_LOGON_NONE = 0,
- TASK_LOGON_PASSWORD = 1,
- TASK_LOGON_S4U = 2,
- TASK_LOGON_INTERACTIVE_TOKEN = 3,
- TASK_LOGON_GROUP = 4,
- TASK_LOGON_SERVICE_ACCOUNT = 5,
- TASK_LOGON_INTERACTIVE_TOKEN_OR_PASSWORD = 6
-}
-
-public enum TASK_RUN_LEVEL
-{
- TASK_RUNLEVEL_LUA = 0,
- TASK_RUNLEVEL_HIGHEST = 1
-}
-
-public enum TASK_STATE
-{
- TASK_STATE_UNKNOWN = 0,
- TASK_STATE_DISABLED = 1,
- TASK_STATE_QUEUED = 2,
- TASK_STATE_READY = 3,
- TASK_STATE_RUNNING = 4
-}
-
-public enum TASK_TRIGGER_TYPE2
-{
- TASK_TRIGGER_EVENT = 0,
- TASK_TRIGGER_TIME = 1,
- TASK_TRIGGER_DAILY = 2,
- TASK_TRIGGER_WEEKLY = 3,
- TASK_TRIGGER_MONTHLY = 4,
- TASK_TRIGGER_MONTHLYDOW = 5,
- TASK_TRIGGER_IDLE = 6,
- TASK_TRIGGER_REGISTRATION = 7,
- TASK_TRIGGER_BOOT = 8,
- TASK_TRIGGER_LOGON = 9,
- TASK_TRIGGER_SESSION_STATE_CHANGE = 11
-}
-"@
-
-$original_tmp = $env:TMP
-$env:TMP = $_remote_tmp
-Add-Type -TypeDefinition $task_enums
-$env:TMP = $original_tmp
-
-Function Get-PropertyValue($task_property, $com, $property) {
- $raw_value = $com.$property
-
- if ($null -eq $raw_value) {
- return $null
- } elseif ($raw_value.GetType().Name -eq "__ComObject") {
- $com_values = @{}
- Get-Member -InputObject $raw_value -MemberType Property | ForEach-Object {
- $com_value = Get-PropertyValue -task_property $property -com $raw_value -property $_.Name
- $com_values.$($_.Name) = $com_value
- }
-
- return ,$com_values
- }
-
- switch ($property) {
- DaysOfWeek {
- $value_list = @()
- $map = @(
- @{ day = "sunday"; bitwise = 0x01 }
- @{ day = "monday"; bitwise = 0x02 }
- @{ day = "tuesday"; bitwise = 0x04 }
- @{ day = "wednesday"; bitwise = 0x08 }
- @{ day = "thursday"; bitwise = 0x10 }
- @{ day = "friday"; bitwise = 0x20 }
- @{ day = "saturday"; bitwise = 0x40 }
- )
- foreach ($entry in $map) {
- $day = $entry.day
- $bitwise = $entry.bitwise
- if ($raw_value -band $bitwise) {
- $value_list += $day
- }
- }
-
- $value = $value_list -join ","
- break
- }
- DaysOfMonth {
- $value_list = @()
- $map = @(
- @{ day = "1"; bitwise = 0x01 }
- @{ day = "2"; bitwise = 0x02 }
- @{ day = "3"; bitwise = 0x04 }
- @{ day = "4"; bitwise = 0x08 }
- @{ day = "5"; bitwise = 0x10 }
- @{ day = "6"; bitwise = 0x20 }
- @{ day = "7"; bitwise = 0x40 }
- @{ day = "8"; bitwise = 0x80 }
- @{ day = "9"; bitwise = 0x100 }
- @{ day = "10"; bitwise = 0x200 }
- @{ day = "11"; bitwise = 0x400 }
- @{ day = "12"; bitwise = 0x800 }
- @{ day = "13"; bitwise = 0x1000 }
- @{ day = "14"; bitwise = 0x2000 }
- @{ day = "15"; bitwise = 0x4000 }
- @{ day = "16"; bitwise = 0x8000 }
- @{ day = "17"; bitwise = 0x10000 }
- @{ day = "18"; bitwise = 0x20000 }
- @{ day = "19"; bitwise = 0x40000 }
- @{ day = "20"; bitwise = 0x80000 }
- @{ day = "21"; bitwise = 0x100000 }
- @{ day = "22"; bitwise = 0x200000 }
- @{ day = "23"; bitwise = 0x400000 }
- @{ day = "24"; bitwise = 0x800000 }
- @{ day = "25"; bitwise = 0x1000000 }
- @{ day = "26"; bitwise = 0x2000000 }
- @{ day = "27"; bitwise = 0x4000000 }
- @{ day = "28"; bitwise = 0x8000000 }
- @{ day = "29"; bitwise = 0x10000000 }
- @{ day = "30"; bitwise = 0x20000000 }
- @{ day = "31"; bitwise = 0x40000000 }
- )
-
- foreach ($entry in $map) {
- $day = $entry.day
- $bitwise = $entry.bitwise
- if ($raw_value -band $bitwise) {
- $value_list += $day
- }
- }
-
- $value = $value_list -join ","
- break
- }
- WeeksOfMonth {
- $value_list = @()
- $map = @(
- @{ week = "1"; bitwise = 0x01 }
- @{ week = "2"; bitwise = 0x02 }
- @{ week = "3"; bitwise = 0x04 }
- @{ week = "4"; bitwise = 0x04 }
- )
-
- foreach ($entry in $map) {
- $week = $entry.week
- $bitwise = $entry.bitwise
- if ($raw_value -band $bitwise) {
- $value_list += $week
- }
- }
-
- $value = $value_list -join ","
- break
- }
- MonthsOfYear {
- $value_list = @()
- $map = @(
- @{ month = "january"; bitwise = 0x01 }
- @{ month = "february"; bitwise = 0x02 }
- @{ month = "march"; bitwise = 0x04 }
- @{ month = "april"; bitwise = 0x08 }
- @{ month = "may"; bitwise = 0x10 }
- @{ month = "june"; bitwise = 0x20 }
- @{ month = "july"; bitwise = 0x40 }
- @{ month = "august"; bitwise = 0x80 }
- @{ month = "september"; bitwise = 0x100 }
- @{ month = "october"; bitwise = 0x200 }
- @{ month = "november"; bitwise = 0x400 }
- @{ month = "december"; bitwise = 0x800 }
- )
-
- foreach ($entry in $map) {
- $month = $entry.month
- $bitwise = $entry.bitwise
- if ($raw_value -band $bitwise) {
- $value_list += $month
- }
- }
-
- $value = $value_list -join ","
- break
- }
- Type {
- if ($task_property -eq "actions") {
- $value = [Enum]::ToObject([TASK_ACTION_TYPE], $raw_value).ToString()
- } elseif ($task_property -eq "triggers") {
- $value = [Enum]::ToObject([TASK_TRIGGER_TYPE2], $raw_value).ToString()
- }
- break
- }
- RunLevel {
- $value = [Enum]::ToObject([TASK_RUN_LEVEL], $raw_value).ToString()
- break
- }
- LogonType {
- $value = [Enum]::ToObject([TASK_LOGON_TYPE], $raw_value).ToString()
- break
- }
- UserId {
- $sid = Convert-ToSID -account_name $raw_value
- $value = Convert-FromSid -sid $sid
- }
- GroupId {
- $sid = Convert-ToSID -account_name $raw_value
- $value = Convert-FromSid -sid $sid
- }
- default {
- $value = $raw_value
- break
- }
- }
-
- return ,$value
-}
-
-$service = New-Object -ComObject Schedule.Service
-try {
- $service.Connect()
-} catch {
- Fail-Json -obj $result -message "failed to connect to the task scheduler service: $($_.Exception.Message)"
-}
-
-try {
- $task_folder = $service.GetFolder($path)
- $result.folder_exists = $true
-} catch {
- $result.folder_exists = $false
- if ($null -ne $name) {
- $result.task_exists = $false
- }
- Exit-Json -obj $result
-}
-
-$folder_tasks = $task_folder.GetTasks(1)
-$folder_task_names = @()
-$folder_task_count = 0
-$task = $null
-for ($i = 1; $i -le $folder_tasks.Count; $i++) {
- $task_name = $folder_tasks.Item($i).Name
- $folder_task_names += $task_name
- $folder_task_count += 1
-
- if ($null -ne $name -and $task_name -eq $name) {
- $task = $folder_tasks.Item($i)
- }
-}
-$result.folder_task_names = $folder_task_names
-$result.folder_task_count = $folder_task_count
-
-if ($null -ne $name) {
- if ($null -ne $task) {
- $result.task_exists = $true
-
- # task state
- $result.state = @{
- last_run_time = (Get-Date $task.LastRunTime -Format s)
- last_task_result = $task.LastTaskResult
- next_run_time = (Get-Date $task.NextRunTime -Format s)
- number_of_missed_runs = $task.NumberOfMissedRuns
- status = [Enum]::ToObject([TASK_STATE], $task.State).ToString()
- }
-
- # task definition
- $task_definition = $task.Definition
- $ignored_properties = @("XmlText")
- $properties = @("principal", "registration_info", "settings")
- $collection_properties = @("actions", "triggers")
-
- foreach ($property in $properties) {
- $property_name = $property -replace "_"
- $result.$property = @{}
- $values = $task_definition.$property_name
- Get-Member -InputObject $values -MemberType Property | ForEach-Object {
- if ($_.Name -notin $ignored_properties) {
- $result.$property.$($_.Name) = (Get-PropertyValue -task_property $property -com $values -property $_.Name)
- }
- }
- }
-
- foreach ($property in $collection_properties) {
- $result.$property = @()
- $collection = $task_definition.$property
- $collection_count = $collection.Count
- for ($i = 1; $i -le $collection_count; $i++) {
- $item = $collection.Item($i)
- $item_info = @{}
-
- Get-Member -InputObject $item -MemberType Property | ForEach-Object {
- if ($_.Name -notin $ignored_properties) {
- $item_info.$($_.Name) = (Get-PropertyValue -task_property $property -com $item -property $_.Name)
- }
- }
- $result.$property += $item_info
- }
- }
- } else {
- $result.task_exists = $false
- }
-}
-
-$result = Convert-DictToSnakeCase -dict $result
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_scheduled_task_stat.py b/lib/ansible/modules/windows/win_scheduled_task_stat.py
deleted file mode 100644
index 1c450c4040..0000000000
--- a/lib/ansible/modules/windows/win_scheduled_task_stat.py
+++ /dev/null
@@ -1,379 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_scheduled_task_stat
-version_added: "2.5"
-short_description: Get information about Windows Scheduled Tasks
-description:
-- Will return whether the folder and task exists.
-- Returns the names of tasks in the folder specified.
-- Use M(win_scheduled_task) to configure a scheduled task.
-options:
- path:
- description: The folder path where the task lives.
- type: str
- default: \
- name:
- description:
- - The name of the scheduled task to get information for.
- - If C(name) is set and exists, will return information on the task itself.
- type: str
-seealso:
-- module: win_scheduled_task
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Get information about a folder
- win_scheduled_task_stat:
- path: \folder name
- register: task_folder_stat
-
-- name: Get information about a task in the root folder
- win_scheduled_task_stat:
- name: task name
- register: task_stat
-
-- name: Get information about a task in a custom folder
- win_scheduled_task_stat:
- path: \folder name
- name: task name
- register: task_stat
-'''
-
-RETURN = r'''
-actions:
- description: A list of actions.
- returned: name is specified and task exists
- type: list
- sample: [
- {
- "Arguments": "/c echo hi",
- "Id": null,
- "Path": "cmd.exe",
- "Type": "TASK_ACTION_EXEC",
- "WorkingDirectory": null
- }
- ]
-folder_exists:
- description: Whether the folder set at path exists.
- returned: always
- type: bool
- sample: true
-folder_task_count:
- description: The number of tasks that exist in the folder.
- returned: always
- type: int
- sample: 2
-folder_task_names:
- description: A list of tasks that exist in the folder.
- returned: always
- type: list
- sample: [ 'Task 1', 'Task 2' ]
-principal:
- description: Details on the principal configured to run the task.
- returned: name is specified and task exists
- type: complex
- contains:
- display_name:
- description: The name of the user/group that is displayed in the Task
- Scheduler UI.
- returned: ''
- type: str
- sample: Administrator
- group_id:
- description: The group that will run the task.
- returned: ''
- type: str
- sample: BUILTIN\Administrators
- id:
- description: The ID for the principal.
- returned: ''
- type: str
- sample: Author
- logon_type:
- description: The logon method that the task will run with.
- returned: ''
- type: str
- sample: TASK_LOGON_INTERACTIVE_TOKEN
- run_level:
- description: The level of user rights used to run the task.
- returned: ''
- type: str
- sample: TASK_RUNLEVEL_LUA
- user_id:
- description: The user that will run the task.
- returned: ''
- type: str
- sample: SERVER\Administrator
-registration_info:
- description: Details on the task registration info.
- returned: name is specified and task exists
- type: complex
- contains:
- author:
- description: The author os the task.
- returned: ''
- type: str
- sample: SERVER\Administrator
- date:
- description: The date when the task was register.
- returned: ''
- type: str
- sample: '2017-01-01T10:00:00'
- description:
- description: The description of the task.
- returned: ''
- type: str
- sample: task description
- documentation:
- description: The documentation of the task.
- returned: ''
- type: str
- sample: task documentation
- security_descriptor:
- description: The security descriptor of the task.
- returned: ''
- type: str
- sample: security descriptor
- source:
- description: The source of the task.
- returned: ''
- type: str
- sample: source
- uri:
- description: The URI/path of the task.
- returned: ''
- type: str
- sample: \task\task name
- version:
- description: The version of the task.
- returned: ''
- type: str
- sample: 1.0
-settings:
- description: Details on the task settings.
- returned: name is specified and task exists
- type: complex
- contains:
- allow_demand_start:
- description: Whether the task can be started by using either the Run
- command of the Context menu.
- returned: ''
- type: bool
- sample: true
- allow_hard_terminate:
- description: Whether the task can terminated by using TerminateProcess.
- returned: ''
- type: bool
- sample: true
- compatibility:
- description: The compatibility level of the task
- returned: ''
- type: int
- sample: 2
- delete_expired_task_after:
- description: The amount of time the Task Scheduler will wait before
- deleting the task after it expires.
- returned: ''
- type: str
- sample: PT10M
- disallow_start_if_on_batteries:
- description: Whether the task will not be started if the computer is
- running on battery power.
- returned: ''
- type: bool
- sample: false
- disallow_start_on_remote_app_session:
- description: Whether the task will not be started when in a remote app
- session.
- returned: ''
- type: bool
- sample: true
- enabled:
- description: Whether the task is enabled.
- returned: ''
- type: bool
- sample: true
- execution_time_limit:
- description: The amount of time allowed to complete the task.
- returned: ''
- type: str
- sample: PT72H
- hidden:
- description: Whether the task is hidden in the UI.
- returned: ''
- type: bool
- sample: false
- idle_settings:
- description: The idle settings of the task.
- returned: ''
- type: dict
- sample: {
- "idle_duration": "PT10M",
- "restart_on_idle": false,
- "stop_on_idle_end": true,
- "wait_timeout": "PT1H"
- }
- maintenance_settings:
- description: The maintenance settings of the task.
- returned: ''
- type: str
- sample: null
- mulitple_instances:
- description: Indicates the behaviour when starting a task that is already
- running.
- returned: ''
- type: int
- sample: 2
- network_settings:
- description: The network settings of the task.
- returned: ''
- type: dict
- sample: {
- "id": null,
- "name": null
- }
- priority:
- description: The priority level of the task.
- returned: ''
- type: int
- sample: 7
- restart_count:
- description: The number of times that the task will attempt to restart
- on failures.
- returned: ''
- type: int
- sample: 0
- restart_interval:
- description: How long the Task Scheduler will attempt to restart the
- task.
- returned: ''
- type: str
- sample: PT15M
- run_only_id_idle:
- description: Whether the task will run if the computer is in an idle
- state.
- returned: ''
- type: bool
- sample: true
- run_only_if_network_available:
- description: Whether the task will run only when a network is available.
- returned: ''
- type: bool
- sample: false
- start_when_available:
- description: Whether the task can start at any time after its scheduled
- time has passed.
- returned: ''
- type: bool
- sample: false
- stop_if_going_on_batteries:
- description: Whether the task will be stopped if the computer begins to
- run on battery power.
- returned: ''
- type: bool
- sample: true
- use_unified_scheduling_engine:
- description: Whether the task will use the unified scheduling engine.
- returned: ''
- type: bool
- sample: false
- volatile:
- description: Whether the task is volatile.
- returned: ''
- type: bool
- sample: false
- wake_to_run:
- description: Whether the task will wake the computer when it is time to
- run the task.
- returned: ''
- type: bool
- sample: false
-state:
- description: Details on the state of the task
- returned: name is specified and task exists
- type: complex
- contains:
- last_run_time:
- description: The time the registered task was last run.
- returned: ''
- type: str
- sample: '2017-09-20T20:50:00'
- last_task_result:
- description: The results that were returned the last time the task was
- run.
- returned: ''
- type: int
- sample: 267009
- next_run_time:
- description: The time when the task is next scheduled to run.
- returned: ''
- type: str
- sample: '2017-09-20T22:50:00'
- number_of_missed_runs:
- description: The number of times a task has missed a scheduled run.
- returned: ''
- type: int
- sample: 1
- status:
- description: The status of the task, whether it is running, stopped, etc.
- returned: ''
- type: str
- sample: TASK_STATE_RUNNING
-task_exists:
- description: Whether the task at the folder exists.
- returned: name is specified
- type: bool
- sample: true
-triggers:
- description: A list of triggers.
- returned: name is specified and task exists
- type: list
- sample: [
- {
- "delay": "PT15M",
- "enabled": true,
- "end_boundary": null,
- "execution_time_limit": null,
- "id": null,
- "repetition": {
- "duration": null,
- "interval": null,
- "stop_at_duration_end": false
- },
- "start_boundary": null,
- "type": "TASK_TRIGGER_BOOT"
- },
- {
- "days_of_month": "5,15,30",
- "enabled": true,
- "end_boundary": null,
- "execution_time_limit": null,
- "id": null,
- "months_of_year": "june,december",
- "random_delay": null,
- "repetition": {
- "duration": null,
- "interval": null,
- "stop_at_duration_end": false
- },
- "run_on_last_day_of_month": true,
- "start_boundary": "2017-09-20T03:44:38",
- "type": "TASK_TRIGGER_MONTHLY"
- }
- ]
-'''
diff --git a/lib/ansible/modules/windows/win_security_policy.ps1 b/lib/ansible/modules/windows/win_security_policy.ps1
deleted file mode 100644
index 274204b6aa..0000000000
--- a/lib/ansible/modules/windows/win_security_policy.ps1
+++ /dev/null
@@ -1,196 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Jordan Borean <jborean93@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = 'Stop'
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$diff_mode = Get-AnsibleParam -obj $Params -name "_ansible_diff" -type "bool" -default $false
-
-$section = Get-AnsibleParam -obj $params -name "section" -type "str" -failifempty $true
-$key = Get-AnsibleParam -obj $params -name "key" -type "str" -failifempty $true
-$value = Get-AnsibleParam -obj $params -name "value" -failifempty $true
-
-$result = @{
- changed = $false
- section = $section
- key = $key
- value = $value
-}
-
-if ($diff_mode) {
- $result.diff = @{}
-}
-
-Function Run-SecEdit($arguments) {
- $stdout = $null
- $stderr = $null
- $log_path = [IO.Path]::GetTempFileName()
- $arguments = $arguments + @("/log", $log_path)
-
- try {
- $stdout = &SecEdit.exe $arguments | Out-String
- } catch {
- $stderr = $_.Exception.Message
- }
- $log = Get-Content -Path $log_path
- Remove-Item -Path $log_path -Force
-
- $return = @{
- log = ($log -join "`n").Trim()
- stdout = $stdout
- stderr = $stderr
- rc = $LASTEXITCODE
- }
-
- return $return
-}
-
-Function Export-SecEdit() {
- $secedit_ini_path = [IO.Path]::GetTempFileName()
- # while this will technically make a change to the system in check mode by
- # creating a new file, we need these values to be able to do anything
- # substantial in check mode
- $export_result = Run-SecEdit -arguments @("/export", "/cfg", $secedit_ini_path, "/quiet")
-
- # check the return code and if the file has been populated, otherwise error out
- if (($export_result.rc -ne 0) -or ((Get-Item -Path $secedit_ini_path).Length -eq 0)) {
- Remove-Item -Path $secedit_ini_path -Force
- $result.rc = $export_result.rc
- $result.stdout = $export_result.stdout
- $result.stderr = $export_result.stderr
- Fail-Json $result "Failed to export secedit.ini file to $($secedit_ini_path)"
- }
- $secedit_ini = ConvertFrom-Ini -file_path $secedit_ini_path
-
- return $secedit_ini
-}
-
-Function Import-SecEdit($ini) {
- $secedit_ini_path = [IO.Path]::GetTempFileName()
- $secedit_db_path = [IO.Path]::GetTempFileName()
- Remove-Item -Path $secedit_db_path -Force # needs to be deleted for SecEdit.exe /import to work
-
- $ini_contents = ConvertTo-Ini -ini $ini
- Set-Content -Path $secedit_ini_path -Value $ini_contents
- $result.changed = $true
-
- $import_result = Run-SecEdit -arguments @("/configure", "/db", $secedit_db_path, "/cfg", $secedit_ini_path, "/quiet")
- $result.import_log = $import_result.log
- Remove-Item -Path $secedit_ini_path -Force
- if ($import_result.rc -ne 0) {
- $result.rc = $import_result.rc
- $result.stdout = $import_result.stdout
- $result.stderr = $import_result.stderr
- Fail-Json $result "Failed to import secedit.ini file from $($secedit_ini_path)"
- }
-}
-
-Function ConvertTo-Ini($ini) {
- $content = @()
- foreach ($key in $ini.GetEnumerator()) {
- $section = $key.Name
- $values = $key.Value
-
- $content += "[$section]"
- foreach ($value in $values.GetEnumerator()) {
- $value_key = $value.Name
- $value_value = $value.Value
-
- if ($null -ne $value_value) {
- $content += "$value_key = $value_value"
- }
- }
- }
-
- return $content -join "`r`n"
-}
-
-Function ConvertFrom-Ini($file_path) {
- $ini = @{}
- switch -Regex -File $file_path {
- "^\[(.+)\]" {
- $section = $matches[1]
- $ini.$section = @{}
- }
- "(.+?)\s*=(.*)" {
- $name = $matches[1].Trim()
- $value = $matches[2].Trim()
- if ($value -match "^\d+$") {
- $value = [int]$value
- } elseif ($value.StartsWith('"') -and $value.EndsWith('"')) {
- $value = $value.Substring(1, $value.Length - 2)
- }
-
- $ini.$section.$name = $value
- }
- }
-
- return $ini
-}
-
-if ($section -eq "Privilege Rights") {
- Add-Warning -obj $result -message "Using this module to edit rights and privileges is error-prone, use the win_user_right module instead"
-}
-
-$will_change = $false
-$secedit_ini = Export-SecEdit
-if (-not ($secedit_ini.ContainsKey($section))) {
- Fail-Json $result "The section '$section' does not exist in SecEdit.exe output ini"
-}
-
-if ($secedit_ini.$section.ContainsKey($key)) {
- $current_value = $secedit_ini.$section.$key
-
- if ($current_value -cne $value) {
- if ($diff_mode) {
- $result.diff.prepared = @"
-[$section]
--$key = $current_value
-+$key = $value
-"@
- }
-
- $secedit_ini.$section.$key = $value
- $will_change = $true
- }
-} elseif ([string]$value -eq "") {
- # Value is requested to be removed, and has already been removed, do nothing
-} else {
- if ($diff_mode) {
- $result.diff.prepared = @"
-[$section]
-+$key = $value
-"@
- }
- $secedit_ini.$section.$key = $value
- $will_change = $true
-}
-
-if ($will_change -eq $true) {
- $result.changed = $true
- if (-not $check_mode) {
- Import-SecEdit -ini $secedit_ini
-
- # secedit doesn't error out on improper entries, re-export and verify
- # the changes occurred
- $verification_ini = Export-SecEdit
- $new_section_values = $verification_ini.$section
- if ($new_section_values.ContainsKey($key)) {
- $new_value = $new_section_values.$key
- if ($new_value -cne $value) {
- Fail-Json $result "Failed to change the value for key '$key' in section '$section', the value is still $new_value"
- }
- } elseif ([string]$value -eq "") {
- # Value was empty, so OK if no longer in the result
- } else {
- Fail-Json $result "The key '$key' in section '$section' is not a valid key, cannot set this value"
- }
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_security_policy.py b/lib/ansible/modules/windows/win_security_policy.py
deleted file mode 100644
index d582a53231..0000000000
--- a/lib/ansible/modules/windows/win_security_policy.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub, actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_security_policy
-version_added: '2.4'
-short_description: Change local security policy settings
-description:
-- Allows you to set the local security policies that are configured by
- SecEdit.exe.
-options:
- section:
- description:
- - The ini section the key exists in.
- - If the section does not exist then the module will return an error.
- - Example sections to use are 'Account Policies', 'Local Policies',
- 'Event Log', 'Restricted Groups', 'System Services', 'Registry' and
- 'File System'
- - If wanting to edit the C(Privilege Rights) section, use the
- M(win_user_right) module instead.
- type: str
- required: yes
- key:
- description:
- - The ini key of the section or policy name to modify.
- - The module will return an error if this key is invalid.
- type: str
- required: yes
- value:
- description:
- - The value for the ini key or policy name.
- - If the key takes in a boolean value then 0 = False and 1 = True.
- type: str
- required: yes
-notes:
-- This module uses the SecEdit.exe tool to configure the values, more details
- of the areas and keys that can be configured can be found here
- U(https://msdn.microsoft.com/en-us/library/bb742512.aspx).
-- If you are in a domain environment these policies may be set by a GPO policy,
- this module can temporarily change these values but the GPO will override
- it if the value differs.
-- You can also run C(SecEdit.exe /export /cfg C:\temp\output.ini) to view the
- current policies set on your system.
-- When assigning user rights, use the M(win_user_right) module instead.
-seealso:
-- module: win_user_right
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Change the guest account name
- win_security_policy:
- section: System Access
- key: NewGuestName
- value: Guest Account
-
-- name: Set the maximum password age
- win_security_policy:
- section: System Access
- key: MaximumPasswordAge
- value: 15
-
-- name: Do not store passwords using reversible encryption
- win_security_policy:
- section: System Access
- key: ClearTextPassword
- value: 0
-
-- name: Enable system events
- win_security_policy:
- section: Event Audit
- key: AuditSystemEvents
- value: 1
-'''
-
-RETURN = r'''
-rc:
- description: The return code after a failure when running SecEdit.exe.
- returned: failure with secedit calls
- type: int
- sample: -1
-stdout:
- description: The output of the STDOUT buffer after a failure when running
- SecEdit.exe.
- returned: failure with secedit calls
- type: str
- sample: check log for error details
-stderr:
- description: The output of the STDERR buffer after a failure when running
- SecEdit.exe.
- returned: failure with secedit calls
- type: str
- sample: failed to import security policy
-import_log:
- description: The log of the SecEdit.exe /configure job that configured the
- local policies. This is used for debugging purposes on failures.
- returned: secedit.exe /import run and change occurred
- type: str
- sample: Completed 6 percent (0/15) \tProcess Privilege Rights area.
-key:
- description: The key in the section passed to the module to modify.
- returned: success
- type: str
- sample: NewGuestName
-section:
- description: The section passed to the module to modify.
- returned: success
- type: str
- sample: System Access
-value:
- description: The value passed to the module to modify to.
- returned: success
- type: str
- sample: Guest Account
-'''
diff --git a/lib/ansible/modules/windows/win_shortcut.ps1 b/lib/ansible/modules/windows/win_shortcut.ps1
deleted file mode 100644
index 291f13cc80..0000000000
--- a/lib/ansible/modules/windows/win_shortcut.ps1
+++ /dev/null
@@ -1,374 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2016, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# Based on: http://powershellblogger.com/2016/01/create-shortcuts-lnk-or-url-files-with-powershell/
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.AddType
-
-$spec = @{
- options = @{
- src = @{ type='str' }
- dest = @{ type='path'; required=$true }
- state = @{ type='str'; default='present'; choices=@( 'absent', 'present' ) }
- arguments = @{ type='str'; aliases=@( 'args' ) }
- directory = @{ type='path' }
- hotkey = @{ type='str' }
- icon = @{ type='path' }
- description = @{ type='str' }
- windowstyle = @{ type='str'; choices=@( 'maximized', 'minimized', 'normal' ) }
- run_as_admin = @{ type='bool'; default=$false }
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$src = $module.Params.src
-$dest = $module.Params.dest
-$state = $module.Params.state
-$arguments = $module.Params.arguments # NOTE: Variable $args is a special variable
-$directory = $module.Params.directory
-$hotkey = $module.Params.hotkey
-$icon = $module.Params.icon
-$description = $module.Params.description
-$windowstyle = $module.Params.windowstyle
-$run_as_admin = $module.Params.run_as_admin
-
-# Expand environment variables on non-path types
-if ($null -ne $src) {
- $src = [System.Environment]::ExpandEnvironmentVariables($src)
-}
-if ($null -ne $arguments) {
- $arguments = [System.Environment]::ExpandEnvironmentVariables($arguments)
-}
-if ($null -ne $description) {
- $description = [System.Environment]::ExpandEnvironmentVariables($description)
-}
-
-$module.Result.changed = $false
-$module.Result.dest = $dest
-$module.Result.state = $state
-
-# TODO: look at consolidating other COM actions into the C# class for future compatibility
-Add-CSharpType -AnsibleModule $module -References @'
-using System;
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.ComTypes;
-using System.Text;
-
-namespace Ansible.Shortcut
-{
- [ComImport()]
- [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- [Guid("000214F9-0000-0000-C000-000000000046")]
- internal interface IShellLinkW
- {
- // We only care about GetPath and GetIDList, omit the other methods for now
- void GetPath(StringBuilder pszFile, int cch, IntPtr pfd, UInt32 fFlags);
- void GetIDList(out IntPtr ppidl);
- }
-
- [ComImport()]
- [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
- [Guid("45E2b4AE-B1C3-11D0-B92F-00A0C90312E1")]
- internal interface IShellLinkDataList
- {
- void AddDataBlock(IntPtr pDataBlock);
- void CopyDataBlock(uint dwSig, out IntPtr ppDataBlock);
- void RemoveDataBlock(uint dwSig);
- void GetFlags(out ShellLinkFlags dwFlags);
- void SetFlags(ShellLinkFlags dwFlags);
- }
-
- internal class NativeHelpers
- {
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
- public struct SHFILEINFO
- {
- public IntPtr hIcon;
- public int iIcon;
- public UInt32 dwAttributes;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 260)] public char[] szDisplayName;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] public char[] szTypeName;
- }
- }
-
- internal class NativeMethods
- {
- [DllImport("shell32.dll")]
- public static extern void ILFree(
- IntPtr pidl);
-
- [DllImport("shell32.dll")]
- public static extern IntPtr SHGetFileInfoW(
- IntPtr pszPath,
- UInt32 dwFileAttributes,
- ref NativeHelpers.SHFILEINFO psfi,
- int sbFileInfo,
- UInt32 uFlags);
-
- [DllImport("shell32.dll")]
- public static extern int SHParseDisplayName(
- [MarshalAs(UnmanagedType.LPWStr)] string pszName,
- IntPtr pbc,
- out IntPtr ppidl,
- UInt32 sfagoIn,
- out UInt32 psfgaoOut);
- }
-
- [System.Flags]
- public enum ShellLinkFlags : uint
- {
- Default = 0x00000000,
- HasIdList = 0x00000001,
- HasLinkInfo = 0x00000002,
- HasName = 0x00000004,
- HasRelPath = 0x00000008,
- HasWorkingDir = 0x00000010,
- HasArgs = 0x00000020,
- HasIconLocation = 0x00000040,
- Unicode = 0x00000080,
- ForceNoLinkInfo = 0x00000100,
- HasExpSz = 0x00000200,
- RunInSeparate = 0x00000400,
- HasLogo3Id = 0x00000800,
- HasDarwinId = 0x00001000,
- RunAsUser = 0x00002000,
- HasExpIconSz = 0x00004000,
- NoPidlAlias = 0x00008000,
- ForceUncName = 0x00010000,
- RunWithShimLayer = 0x00020000,
- ForceNoLinkTrack = 0x00040000,
- EnableTargetMetadata = 0x00080000,
- DisableLinkPathTracking = 0x00100000,
- DisableKnownFolderRelativeTracking = 0x00200000,
- NoKfAlias = 0x00400000,
- AllowLinkToLink = 0x00800000,
- UnAliasOnSave = 0x01000000,
- PreferEnvironmentPath = 0x02000000,
- KeepLocalIdListForUncTarget = 0x04000000,
- PersistVolumeIdToRelative = 0x08000000,
- Valid = 0x0FFFF7FF,
- Reserved = 0x80000000
- }
-
- public class ShellLink
- {
- private static Guid CLSID_ShellLink = new Guid("00021401-0000-0000-C000-000000000046");
-
- public static ShellLinkFlags GetFlags(string path)
- {
- IShellLinkW link = InitialiseObj(path);
- ShellLinkFlags dwFlags;
- ((IShellLinkDataList)link).GetFlags(out dwFlags);
- return dwFlags;
- }
-
- public static void SetFlags(string path, ShellLinkFlags flags)
- {
- IShellLinkW link = InitialiseObj(path);
- ((IShellLinkDataList)link).SetFlags(flags);
- ((IPersistFile)link).Save(null, false);
- }
-
- public static string GetTargetPath(string path)
- {
- IShellLinkW link = InitialiseObj(path);
-
- StringBuilder pathSb = new StringBuilder(260);
- link.GetPath(pathSb, pathSb.Capacity, IntPtr.Zero, 0);
- string linkPath = pathSb.ToString();
-
- // If the path wasn't set, try and get the path from the ItemIDList
- ShellLinkFlags flags = GetFlags(path);
- if (String.IsNullOrEmpty(linkPath) && ((uint)flags & (uint)ShellLinkFlags.HasIdList) == (uint)ShellLinkFlags.HasIdList)
- {
- IntPtr idList = IntPtr.Zero;
- try
- {
- link.GetIDList(out idList);
- linkPath = GetDisplayNameFromPidl(idList);
- }
- finally
- {
- NativeMethods.ILFree(idList);
- }
- }
- return linkPath;
- }
-
- public static string GetDisplayNameFromPath(string path)
- {
- UInt32 sfgaoOut;
- IntPtr pidl = IntPtr.Zero;
- try
- {
- int res = NativeMethods.SHParseDisplayName(path, IntPtr.Zero, out pidl, 0, out sfgaoOut);
- Marshal.ThrowExceptionForHR(res);
- return GetDisplayNameFromPidl(pidl);
- }
- finally
- {
- NativeMethods.ILFree(pidl);
- }
- }
-
- private static string GetDisplayNameFromPidl(IntPtr pidl)
- {
- NativeHelpers.SHFILEINFO shFileInfo = new NativeHelpers.SHFILEINFO();
- UInt32 uFlags = 0x000000208; // SHGFI_DISPLAYNAME | SHGFI_PIDL
- NativeMethods.SHGetFileInfoW(pidl, 0, ref shFileInfo, Marshal.SizeOf(typeof(NativeHelpers.SHFILEINFO)), uFlags);
- return new string(shFileInfo.szDisplayName).TrimEnd('\0');
- }
-
- private static IShellLinkW InitialiseObj(string path)
- {
- IShellLinkW link = Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_ShellLink)) as IShellLinkW;
- ((IPersistFile)link).Load(path, 0);
- return link;
- }
- }
-}
-'@
-
-# Convert from window style name to window style id
-$windowstyles = @{
- normal = 1
- maximized = 3
- minimized = 7
-}
-
-# Convert from window style id to window style name
-$windowstyleids = @( "", "normal", "", "maximized", "", "", "", "minimized" )
-
-If ($state -eq "absent") {
- If (Test-Path -Path $dest) {
- # If the shortcut exists, try to remove it
- Try {
- Remove-Item -Path $dest -WhatIf:$module.CheckMode
- } Catch {
- # Report removal failure
- $module.FailJson("Failed to remove shortcut '$dest'. ($($_.Exception.Message))", $_)
- }
- # Report removal success
- $module.Result.changed = $true
- } Else {
- # Nothing to report, everything is fine already
- }
-} ElseIf ($state -eq "present") {
- # Create an in-memory object based on the existing shortcut (if any)
- $Shell = New-Object -ComObject ("WScript.Shell")
- $ShortCut = $Shell.CreateShortcut($dest)
-
- # Compare existing values with new values, report as changed if required
-
- If ($null -ne $src) {
- # Windows translates executables to absolute path, so do we
- If (Get-Command -Name $src -Type Application -ErrorAction SilentlyContinue) {
- $src = (Get-Command -Name $src -Type Application).Definition
- }
- If (-not (Test-Path -Path $src -IsValid)) {
- If (-not (Split-Path -Path $src -IsAbsolute)) {
- $module.FailJson("Source '$src' is not found in PATH and not a valid or absolute path.")
- }
- }
- }
-
- # Determine if we have a WshShortcut or WshUrlShortcut by checking the Arguments property
- # A WshUrlShortcut objects only consists of a TargetPath property
-
- $file_shortcut = $false
- If (Get-Member -InputObject $ShortCut -Name Arguments) {
- # File ShortCut, compare multiple properties
- $file_shortcut = $true
-
- $target_path = $ShortCut.TargetPath
- If (($null -ne $src) -and ($ShortCut.TargetPath -ne $src)) {
- if ((Test-Path -Path $dest) -and (-not $ShortCut.TargetPath)) {
- # If the shortcut already exists but not on the COM object, we
- # are dealing with a shell path like 'shell:RecycleBinFolder'.
- $expanded_src = [Ansible.Shortcut.ShellLink]::GetDisplayNameFromPath($src)
- $actual_src = [Ansible.Shortcut.ShellLink]::GetTargetPath($dest)
- if ($expanded_src -ne $actual_src) {
- $module.Result.changed = $true
- $ShortCut.TargetPath = $src
- }
- } else {
- $module.Result.changed = $true
- $ShortCut.TargetPath = $src
- }
- $target_path = $src
- }
-
- # This is a full-featured application shortcut !
- If (($null -ne $arguments) -and ($ShortCut.Arguments -ne $arguments)) {
- $module.Result.changed = $true
- $ShortCut.Arguments = $arguments
- }
- $module.Result.args = $ShortCut.Arguments
-
- If (($null -ne $directory) -and ($ShortCut.WorkingDirectory -ne $directory)) {
- $module.Result.changed = $true
- $ShortCut.WorkingDirectory = $directory
- }
- $module.Result.directory = $ShortCut.WorkingDirectory
-
- # FIXME: Not all values are accepted here ! Improve docs too.
- If (($null -ne $hotkey) -and ($ShortCut.Hotkey -ne $hotkey)) {
- $module.Result.changed = $true
- $ShortCut.Hotkey = $hotkey
- }
- $module.Result.hotkey = $ShortCut.Hotkey
-
- If (($null -ne $icon) -and ($ShortCut.IconLocation -ne $icon)) {
- $module.Result.changed = $true
- $ShortCut.IconLocation = $icon
- }
- $module.Result.icon = $ShortCut.IconLocation
-
- If (($null -ne $description) -and ($ShortCut.Description -ne $description)) {
- $module.Result.changed = $true
- $ShortCut.Description = $description
- }
- $module.Result.description = $ShortCut.Description
-
- If (($null -ne $windowstyle) -and ($ShortCut.WindowStyle -ne $windowstyles.$windowstyle)) {
- $module.Result.changed = $true
- $ShortCut.WindowStyle = $windowstyles.$windowstyle
- }
- $module.Result.windowstyle = $windowstyleids[$ShortCut.WindowStyle]
- } else {
- # URL Shortcut, just compare the TargetPath
- if (($null -ne $src) -and ($ShortCut.TargetPath -ne $src)) {
- $module.Result.changed = $true
- $ShortCut.TargetPath = $src
- }
- $target_path = $ShortCut.TargetPath
- }
- $module.Result.src = $target_path
-
- If (($module.Result.changed -eq $true) -and ($module.CheckMode -ne $true)) {
- Try {
- $ShortCut.Save()
- } Catch {
- $module.FailJson("Failed to create shortcut '$dest'. ($($_.Exception.Message))", $_)
- }
- }
-
- if ((Test-Path -Path $dest) -and $file_shortcut) {
- # Only control the run_as_admin flag if using a File Shortcut
- $flags = [Ansible.Shortcut.ShellLink]::GetFlags($dest)
- if ($run_as_admin -and (-not $flags.HasFlag([Ansible.Shortcut.ShellLinkFlags]::RunAsUser))) {
- [Ansible.Shortcut.ShellLink]::SetFlags($dest, ($flags -bor [Ansible.Shortcut.ShellLinkFlags]::RunAsUser))
- $module.Result.changed = $true
- } elseif (-not $run_as_admin -and ($flags.HasFlag([Ansible.Shortcut.ShellLinkFlags]::RunAsUser))) {
- [Ansible.Shortcut.ShellLink]::SetFlags($dest, ($flags -bxor [Ansible.Shortcut.ShellLinkFlags]::RunAsUser))
- $module.Result.changed = $true
- }
- }
-}
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_shortcut.py b/lib/ansible/modules/windows/win_shortcut.py
deleted file mode 100644
index 2fe2ff4292..0000000000
--- a/lib/ansible/modules/windows/win_shortcut.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2016, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_shortcut
-version_added: '2.3'
-short_description: Manage shortcuts on Windows
-description:
-- Create, manage and delete Windows shortcuts
-options:
- src:
- description:
- - Executable or URL the shortcut points to.
- - The executable needs to be in your PATH, or has to be an absolute
- path to the executable.
- type: str
- description:
- description:
- - Description for the shortcut.
- - This is usually shown when hoovering the icon.
- type: str
- dest:
- description:
- - Destination file for the shortcuting file.
- - File name should have a C(.lnk) or C(.url) extension.
- type: path
- required: yes
- arguments:
- description:
- - Additional arguments for the executable defined in C(src).
- - Was originally just C(args) but renamed in Ansible 2.8.
- type: str
- aliases: [ args ]
- directory:
- description:
- - Working directory for executable defined in C(src).
- type: path
- icon:
- description:
- - Icon used for the shortcut.
- - File name should have a C(.ico) extension.
- - The file name is followed by a comma and the number in the library file (.dll) or use 0 for an image file.
- type: path
- hotkey:
- description:
- - Key combination for the shortcut.
- - This is a combination of one or more modifiers and a key.
- - Possible modifiers are Alt, Ctrl, Shift, Ext.
- - Possible keys are [A-Z] and [0-9].
- type: str
- windowstyle:
- description:
- - Influences how the application is displayed when it is launched.
- type: str
- choices: [ maximized, minimized, normal ]
- state:
- description:
- - When C(absent), removes the shortcut if it exists.
- - When C(present), creates or updates the shortcut.
- type: str
- choices: [ absent, present ]
- default: present
- run_as_admin:
- description:
- - When C(src) is an executable, this can control whether the shortcut will be opened as an administrator or not.
- type: bool
- default: no
- version_added: '2.8'
-notes:
-- 'The following options can include Windows environment variables: C(dest), C(args), C(description), C(dest), C(directory), C(icon) C(src)'
-- 'Windows has two types of shortcuts: Application and URL shortcuts. URL shortcuts only consists of C(dest) and C(src)'
-seealso:
-- module: win_file
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-EXAMPLES = r'''
-- name: Create an application shortcut on the desktop
- win_shortcut:
- src: C:\Program Files\Mozilla Firefox\Firefox.exe
- dest: C:\Users\Public\Desktop\Mozilla Firefox.lnk
- icon: C:\Program Files\Mozilla Firefox\Firefox.exe,0
-
-- name: Create the same shortcut using environment variables
- win_shortcut:
- description: The Mozilla Firefox web browser
- src: '%ProgramFiles%\Mozilla Firefox\Firefox.exe'
- dest: '%Public%\Desktop\Mozilla Firefox.lnk'
- icon: '%ProgramFiles\Mozilla Firefox\Firefox.exe,0'
- directory: '%ProgramFiles%\Mozilla Firefox'
- hotkey: Ctrl+Alt+F
-
-- name: Create an application shortcut for an executable in PATH to your desktop
- win_shortcut:
- src: cmd.exe
- dest: Desktop\Command prompt.lnk
-
-- name: Create an application shortcut for the Ansible website
- win_shortcut:
- src: '%ProgramFiles%\Google\Chrome\Application\chrome.exe'
- dest: '%UserProfile%\Desktop\Ansible website.lnk'
- arguments: --new-window https://ansible.com/
- directory: '%ProgramFiles%\Google\Chrome\Application'
- icon: '%ProgramFiles%\Google\Chrome\Application\chrome.exe,0'
- hotkey: Ctrl+Alt+A
-
-- name: Create a URL shortcut for the Ansible website
- win_shortcut:
- src: https://ansible.com/
- dest: '%Public%\Desktop\Ansible website.url'
-'''
-
-RETURN = r'''
-'''
diff --git a/lib/ansible/modules/windows/win_snmp.ps1 b/lib/ansible/modules/windows/win_snmp.ps1
deleted file mode 100644
index 48e03253fe..0000000000
--- a/lib/ansible/modules/windows/win_snmp.ps1
+++ /dev/null
@@ -1,126 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$params = Parse-Args -arguments $args -supports_check_mode $true;
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-$managers = Get-AnsibleParam -obj $params -name "permitted_managers" -type "list" -default $null
-$communities = Get-AnsibleParam -obj $params -name "community_strings" -type "list" -default $null
-$action_in = Get-AnsibleParam -obj $params -name "action" -type "str" -default "set" -ValidateSet @("set", "add", "remove")
-$action = $action_in.ToLower()
-
-$result = @{
- failed = $False
- changed = $False
- community_strings = [System.Collections.ArrayList]@()
- permitted_managers = [System.Collections.ArrayList]@()
-}
-
-# Make sure lists are modifyable
-[System.Collections.ArrayList]$managers = $managers
-[System.Collections.ArrayList]$communities = $communities
-[System.Collections.ArrayList]$indexes = @()
-
-# Type checking
-# You would think that "$null -ne $managers" would work, but it doesn't.
-# A proper type check is required. If a user provides an empty list then $managers
-# is still of the correct type. If a user provides no option then $managers is $null.
-If ($managers -Is [System.Collections.ArrayList] -And $managers.Count -gt 0 -And $managers[0] -IsNot [String]) {
- Fail-Json $result "Permitted managers must be an array of strings"
-}
-
-If ($communities -Is [System.Collections.ArrayList] -And $communities.Count -gt 0 -And $communities[0] -IsNot [String]) {
- Fail-Json $result "SNMP communities must be an array of strings"
-}
-
-$Managers_reg_key = "HKLM:\System\CurrentControlSet\services\SNMP\Parameters\PermittedManagers"
-$Communities_reg_key = "HKLM:\System\CurrentControlSet\services\SNMP\Parameters\ValidCommunities"
-
-ForEach ($idx in (Get-Item $Managers_reg_key).Property) {
- $manager = (Get-ItemProperty $Managers_reg_key).$idx
- If ($idx.ToLower() -eq '(default)') {
- continue
- }
-
- $remove = $False
- If ($managers -Is [System.Collections.ArrayList] -And $managers.Contains($manager)) {
- If ($action -eq "remove") {
- $remove = $True
- } Else {
- # Remove manager from list to add since it already exists
- $managers.Remove($manager)
- }
- } ElseIf ($action -eq "set" -And $managers -Is [System.Collections.ArrayList]) {
- # Will remove this manager since it is not in the set list
- $remove = $True
- }
-
- If ($remove) {
- $result.changed = $True
- Remove-ItemProperty -Path $Managers_reg_key -Name $idx -WhatIf:$check_mode
- } Else {
- # Remember that this index is in use
- $indexes.Add([int]$idx) | Out-Null
- $result.permitted_managers.Add($manager) | Out-Null
- }
-}
-
-ForEach ($community in (Get-Item $Communities_reg_key).Property) {
- If ($community.ToLower() -eq '(default)') {
- continue
- }
-
- $remove = $False
- If ($communities -Is [System.Collections.ArrayList] -And $communities.Contains($community)) {
- If ($action -eq "remove") {
- $remove = $True
- } Else {
- # Remove community from list to add since it already exists
- $communities.Remove($community)
- }
- } ElseIf ($action -eq "set" -And $communities -Is [System.Collections.ArrayList]) {
- # Will remove this community since it is not in the set list
- $remove = $True
- }
-
- If ($remove) {
- $result.changed = $True
- Remove-ItemProperty -Path $Communities_reg_key -Name $community -WhatIf:$check_mode
- } Else {
- $result.community_strings.Add($community) | Out-Null
- }
-}
-
-If ($action -eq "remove") {
- Exit-Json $result
-}
-
-# Add managers that don't already exist
-$next_index = 0
-If ($managers -Is [System.Collections.ArrayList]) {
- ForEach ($manager in $managers) {
- While ($True) {
- $next_index = $next_index + 1
- If (-Not $indexes.Contains($next_index)) {
- $result.changed = $True
- New-ItemProperty -Path $Managers_reg_key -Name $next_index -Value "$manager" -WhatIf:$check_mode | Out-Null
- $result.permitted_managers.Add($manager) | Out-Null
- break
- }
- }
- }
-}
-
-# Add communities that don't already exist
-If ($communities -Is [System.Collections.ArrayList]) {
- ForEach ($community in $communities) {
- $result.changed = $True
- New-ItemProperty -Path $Communities_reg_key -Name $community -PropertyType DWord -Value 4 -WhatIf:$check_mode | Out-Null
- $result.community_strings.Add($community) | Out-Null
- }
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_snmp.py b/lib/ansible/modules/windows/win_snmp.py
deleted file mode 100644
index df9a577082..0000000000
--- a/lib/ansible/modules/windows/win_snmp.py
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ansible, inc
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {
- 'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'
-}
-
-DOCUMENTATION = r'''
----
-module: win_snmp
-version_added: '2.8'
-short_description: Configures the Windows SNMP service
-description:
- - This module configures the Windows SNMP service.
-options:
- permitted_managers:
- description:
- - The list of permitted SNMP managers.
- type: list
- community_strings:
- description:
- - The list of read-only SNMP community strings.
- type: list
- action:
- description:
- - C(add) will add new SNMP community strings and/or SNMP managers
- - C(set) will replace SNMP community strings and/or SNMP managers. An
- empty list for either C(community_strings) or C(permitted_managers)
- will result in the respective lists being removed entirely.
- - C(remove) will remove SNMP community strings and/or SNMP managers
- type: str
- choices: [ add, set, remove ]
- default: set
-author:
- - Michael Cassaniti (@mcassaniti)
-'''
-
-EXAMPLES = r'''
----
- - hosts: Windows
- tasks:
- - name: Replace SNMP communities and managers
- win_snmp:
- community_strings:
- - public
- permitted_managers:
- - 192.168.1.2
- action: set
-
- - hosts: Windows
- tasks:
- - name: Replace SNMP communities and clear managers
- win_snmp:
- community_strings:
- - public
- permitted_managers: []
- action: set
-'''
-
-RETURN = r'''
-community_strings:
- description: The list of community strings for this machine.
- type: list
- returned: always
- sample:
- - public
- - snmp-ro
-permitted_managers:
- description: The list of permitted managers for this machine.
- type: list
- returned: always
- sample:
- - 192.168.1.1
- - 192.168.1.2
-'''
diff --git a/lib/ansible/modules/windows/win_timezone.ps1 b/lib/ansible/modules/windows/win_timezone.ps1
deleted file mode 100644
index f46a11c3ad..0000000000
--- a/lib/ansible/modules/windows/win_timezone.ps1
+++ /dev/null
@@ -1,70 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Phil Schwartz <schwartzmx@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$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
-
-$timezone = Get-AnsibleParam -obj $params -name "timezone" -type "str" -failifempty $true
-
-$result = @{
- changed = $false
- previous_timezone = $timezone
- timezone = $timezone
-}
-
-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."
- }
-
- 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."
- }
-
- $tzExists = $tzList.Contains(($timezone -Replace '_dstoff').ToLower())
- if (-not $tzExists) {
- Fail-Json $result "The specified timezone: $timezone isn't supported on the machine."
- }
-
- 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
- }
- }
-
- if ($diff_support) {
- $result.diff = @{
- before = "$($result.previous_timezone)`n"
- after = "$timezone`n"
- }
- }
- }
-} Catch {
- Fail-Json $result "Error setting timezone to: $timezone."
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_timezone.py b/lib/ansible/modules/windows/win_timezone.py
deleted file mode 100644
index a3b66c9e56..0000000000
--- a/lib/ansible/modules/windows/win_timezone.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Phil Schwartz <schwartzmx@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_timezone
-version_added: '2.1'
-short_description: Sets Windows machine timezone
-description:
-- Sets machine time to the specified timezone.
-options:
- timezone:
- description:
- - Timezone to set to.
- - 'Example: Central Standard Time'
- - To disable Daylight Saving time, add the suffix C(_dstoff) on timezones that support this.
- type: str
- required: yes
-notes:
-- The module will check if the provided timezone is supported on the machine.
-- A list of possible timezones is available from C(tzutil.exe /l) and from
- U(https://msdn.microsoft.com/en-us/library/ms912391.aspx)
-- If running on Server 2008 the hotfix
- U(https://support.microsoft.com/en-us/help/2556308/tzutil-command-line-tool-is-added-to-windows-vista-and-to-windows-server-2008)
- needs to be installed to be able to run this module.
-seealso:
-- module: win_region
-author:
-- Phil Schwartz (@schwartzmx)
-'''
-
-EXAMPLES = r'''
-- name: Set timezone to 'Romance Standard Time' (GMT+01:00)
- win_timezone:
- timezone: Romance Standard Time
-
-- name: Set timezone to 'GMT Standard Time' (GMT)
- win_timezone:
- timezone: GMT Standard Time
-
-- name: Set timezone to 'Central Standard Time' (GMT-06:00)
- win_timezone:
- timezone: Central Standard Time
-
-- name: Set timezime to Pacific Standard time and disable Daylight Saving time adjustments
- win_timezone:
- timezone: Pacific Standard Time_dstoff
-'''
-
-RETURN = r'''
-previous_timezone:
- description: The previous timezone if it was changed, otherwise the existing timezone.
- returned: success
- type: str
- sample: Central Standard Time
-timezone:
- description: The current timezone (possibly changed).
- returned: success
- type: str
- sample: Central Standard Time
-'''
diff --git a/lib/ansible/modules/windows/win_toast.ps1 b/lib/ansible/modules/windows/win_toast.ps1
deleted file mode 100644
index e993651521..0000000000
--- a/lib/ansible/modules/windows/win_toast.ps1
+++ /dev/null
@@ -1,90 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Jon Hawkesworth (@jhawkesworth) <figs@unity.demon.co.uk>
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-# version check
-$osversion = [Environment]::OSVersion
-$lowest_version = 10
-if ($osversion.Version.Major -lt $lowest_version ) {
- Fail-Json -obj $result -message "Sorry, this version of windows, $osversion, does not support Toast notifications. Toast notifications are available from version $lowest_version"
-}
-
-$stopwatch = [system.diagnostics.stopwatch]::startNew()
-$now = [DateTime]::Now
-$default_title = "Notification: " + $now.ToShortTimeString()
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$expire_seconds = Get-AnsibleParam -obj $params -name "expire" -type "int" -default 45
-$group = Get-AnsibleParam -obj $params -name "group" -type "str" -default "Powershell"
-$msg = Get-AnsibleParam -obj $params -name "msg" -type "str" -default "Hello world!"
-$popup = Get-AnsibleParam -obj $params -name "popup" -type "bool" -default $true
-$tag = Get-AnsibleParam -obj $params -name "tag" -type "str" -default "Ansible"
-$title = Get-AnsibleParam -obj $params -name "title" -type "str" -default $default_title
-
-$timespan = New-TimeSpan -Seconds $expire_seconds
-$expire_at = $now + $timespan
-$expire_at_utc = $($expire_at.ToUniversalTime()|Out-String).Trim()
-
-$result = @{
- changed = $false
- expire_at = $expire_at.ToString()
- expire_at_utc = $expire_at_utc
- toast_sent = $false
-}
-
-# If no logged in users, there is no notifications service,
-# and no-one to read the message, so exit but do not fail
-# if there are no logged in users to notify.
-
-if ((Get-Process -Name explorer -ErrorAction SilentlyContinue).Count -gt 0){
-
- [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
- $template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText01)
-
- #Convert to .NET type for XML manipulation
- $toastXml = [xml] $template.GetXml()
- $toastXml.GetElementsByTagName("text").AppendChild($toastXml.CreateTextNode($title)) > $null
- # TODO add subtitle
-
- #Convert back to WinRT type
- $xml = New-Object Windows.Data.Xml.Dom.XmlDocument
- $xml.LoadXml($toastXml.OuterXml)
-
- $toast = [Windows.UI.Notifications.ToastNotification]::new($xml)
- $toast.Tag = $tag
- $toast.Group = $group
- $toast.ExpirationTime = $expire_at
- $toast.SuppressPopup = -not $popup
-
- try {
- $notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($msg)
- if (-not $check_mode) {
- $notifier.Show($toast)
- $result.toast_sent = $true
- Start-Sleep -Seconds $expire_seconds
- }
- } catch {
- $excep = $_
- $result.exception = $excep.ScriptStackTrace
- Fail-Json -obj $result -message "Failed to create toast notifier: $($excep.Exception.Message)"
- }
-} else {
- $result.toast_sent = $false
- $result.no_toast_sent_reason = 'No logged in users to notify'
-}
-
-$endsend_at = Get-Date | Out-String
-$stopwatch.Stop()
-
-$result.time_taken = $stopwatch.Elapsed.TotalSeconds
-$result.sent_localtime = $endsend_at.Trim()
-
-Exit-Json -obj $result
diff --git a/lib/ansible/modules/windows/win_toast.py b/lib/ansible/modules/windows/win_toast.py
deleted file mode 100644
index 5bb28c8ebb..0000000000
--- a/lib/ansible/modules/windows/win_toast.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Jon Hawkesworth (@jhawkesworth) <figs@unity.demon.co.uk>
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_toast
-version_added: "2.4"
-short_description: Sends Toast windows notification to logged in users on Windows 10 or later hosts
-description:
- - Sends alerts which appear in the Action Center area of the windows desktop.
-options:
- expire:
- description:
- - How long in seconds before the notification expires.
- type: int
- default: 45
- group:
- description:
- - Which notification group to add the notification to.
- type: str
- default: Powershell
- msg:
- description:
- - The message to appear inside the notification.
- - May include \n to format the message to appear within the Action Center.
- type: str
- default: Hello, World!
- popup:
- description:
- - If C(no), the notification will not pop up and will only appear in the Action Center.
- type: bool
- default: yes
- tag:
- description:
- - The tag to add to the notification.
- type: str
- default: Ansible
- title:
- description:
- - The notification title, which appears in the pop up..
- type: str
- default: Notification HH:mm
-notes:
- - This module must run on a windows 10 or Server 2016 host, so ensure your play targets windows hosts, or delegates to a windows host.
- - The module does not fail if there are no logged in users to notify.
- - Messages are only sent to the local host where the module is run.
- - You must run this module with async, otherwise it will hang until the expire period has passed.
-seealso:
-- module: win_msg
-- module: win_say
-author:
-- Jon Hawkesworth (@jhawkesworth)
-'''
-
-EXAMPLES = r'''
-- name: Warn logged in users of impending upgrade (note use of async to stop the module from waiting until notification expires).
- win_toast:
- expire: 60
- title: System Upgrade Notification
- msg: Automated upgrade about to start. Please save your work and log off before {{ deployment_start_time }}
- async: 60
- poll: 0
-'''
-
-RETURN = r'''
-expire_at_utc:
- description: Calculated utc date time when the notification expires.
- returned: always
- type: str
- sample: 07 July 2017 04:50:54
-no_toast_sent_reason:
- description: Text containing the reason why a notification was not sent.
- returned: when no logged in users are detected
- type: str
- sample: No logged in users to notify
-sent_localtime:
- description: local date time when the notification was sent.
- returned: always
- type: str
- sample: 07 July 2017 05:45:54
-time_taken:
- description: How long the module took to run on the remote windows host in seconds.
- returned: always
- type: float
- sample: 0.3706631999999997
-toast_sent:
- description: Whether the module was able to send a toast notification or not.
- returned: always
- type: bool
- sample: false
-'''
diff --git a/lib/ansible/modules/windows/win_unzip.ps1 b/lib/ansible/modules/windows/win_unzip.ps1
deleted file mode 100644
index b49e808845..0000000000
--- a/lib/ansible/modules/windows/win_unzip.ps1
+++ /dev/null
@@ -1,178 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Phil Schwartz <schwartzmx@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-# TODO: This module is not idempotent (it will always unzip and report change)
-
-$ErrorActionPreference = "Stop"
-
-$pcx_extensions = @('.bz2', '.gz', '.msu', '.tar', '.zip')
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$src = Get-AnsibleParam -obj $params -name "src" -type "path" -failifempty $true
-$dest = Get-AnsibleParam -obj $params -name "dest" -type "path" -failifempty $true
-$creates = Get-AnsibleParam -obj $params -name "creates" -type "path"
-$recurse = Get-AnsibleParam -obj $params -name "recurse" -type "bool" -default $false
-$delete_archive = Get-AnsibleParam -obj $params -name "delete_archive" -type "bool" -default $false -aliases 'rm'
-
-# Fixes a fail error message (when the task actually succeeds) for a
-# "Convert-ToJson: The converted JSON string is in bad format"
-# This happens when JSON is parsing a string that ends with a "\",
-# which is possible when specifying a directory to download to.
-# This catches that possible error, before assigning the JSON $result
-$result = @{
- changed = $false
- dest = $dest -replace '\$',''
- removed = $false
- src = $src -replace '\$',''
-}
-
-Function Extract-Zip($src, $dest) {
- $archive = [System.IO.Compression.ZipFile]::Open($src, [System.IO.Compression.ZipArchiveMode]::Read, [System.Text.Encoding]::UTF8)
- foreach ($entry in $archive.Entries) {
- $archive_name = $entry.FullName
-
- $entry_target_path = [System.IO.Path]::Combine($dest, $archive_name)
- $entry_dir = [System.IO.Path]::GetDirectoryName($entry_target_path)
-
- # Normalize paths for further evaluation
- $full_target_path = [System.IO.Path]::GetFullPath($entry_target_path)
- $full_dest_path = [System.IO.Path]::GetFullPath($dest + [System.IO.Path]::DirectorySeparatorChar)
-
- # Ensure file in the archive does not escape the extraction path
- if (-not $full_target_path.StartsWith($full_dest_path)) {
- Fail-Json -obj $result -message "Error unzipping '$src' to '$dest'! Filename contains relative paths which would extract outside the destination: $entry_target_path"
- }
-
- if (-not (Test-Path -LiteralPath $entry_dir)) {
- New-Item -Path $entry_dir -ItemType Directory -WhatIf:$check_mode | Out-Null
- $result.changed = $true
- }
-
- if ((-not ($entry_target_path.EndsWith("\") -or $entry_target_path.EndsWith("/"))) -and (-not $check_mode)) {
- [System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $entry_target_path, $true)
- }
- $result.changed = $true
- }
- $archive.Dispose()
-}
-
-Function Extract-ZipLegacy($src, $dest) {
- # [System.IO.Compression.ZipFile] was only added in .net 4.5, this is used
- # when .net is older than that.
- $shell = New-Object -ComObject Shell.Application
- $zip = $shell.NameSpace([IO.Path]::GetFullPath($src))
- $dest_path = $shell.NameSpace([IO.Path]::GetFullPath($dest))
-
- $shell = New-Object -ComObject Shell.Application
-
- if (-not $check_mode) {
- # https://msdn.microsoft.com/en-us/library/windows/desktop/bb787866.aspx
- # From Folder.CopyHere documentation, 1044 means:
- # - 1024: do not display a user interface if an error occurs
- # - 16: respond with "yes to all" for any dialog box that is displayed
- # - 4: do not display a progress dialog box
- $dest_path.CopyHere($zip.Items(), 1044)
- }
- $result.changed = $true
-}
-
-If ($creates -and (Test-Path -LiteralPath $creates)) {
- $result.skipped = $true
- $result.msg = "The file or directory '$creates' already exists."
- Exit-Json -obj $result
-}
-
-If (-Not (Test-Path -LiteralPath $src)) {
- Fail-Json -obj $result -message "File '$src' does not exist."
-}
-
-$ext = [System.IO.Path]::GetExtension($src)
-
-If (-Not (Test-Path -LiteralPath $dest -PathType Container)){
- Try{
- New-Item -ItemType "directory" -path $dest -WhatIf:$check_mode | out-null
- } Catch {
- Fail-Json -obj $result -message "Error creating '$dest' directory! Msg: $($_.Exception.Message)"
- }
-}
-
-If ($ext -eq ".zip" -And $recurse -eq $false) {
- # TODO: PS v5 supports zip extraction, use that if available
- $use_legacy = $false
- try {
- # determines if .net 4.5 is available, if this fails we need to fall
- # back to the legacy COM Shell.Application to extract the zip
- Add-Type -AssemblyName System.IO.Compression.FileSystem | Out-Null
- Add-Type -AssemblyName System.IO.Compression | Out-Null
- } catch {
- $use_legacy = $true
- }
-
- if ($use_legacy) {
- try {
- Extract-ZipLegacy -src $src -dest $dest
- } catch {
- Fail-Json -obj $result -message "Error unzipping '$src' to '$dest'!. Method: COM Shell.Application, Exception: $($_.Exception.Message)"
- }
- } else {
- try {
- Extract-Zip -src $src -dest $dest
- } catch {
- Fail-Json -obj $result -message "Error unzipping '$src' to '$dest'!. Method: System.IO.Compression.ZipFile, Exception: $($_.Exception.Message)"
- }
- }
-} Else {
- # Check if PSCX is installed
- $list = Get-Module -ListAvailable
-
- If (-Not ($list -match "PSCX")) {
- Fail-Json -obj $result -message "PowerShellCommunityExtensions PowerShell Module (PSCX) is required for non-'.zip' compressed archive types."
- } Else {
- $result.pscx_status = "present"
- }
-
- Try {
- Import-Module PSCX
- }
- Catch {
- Fail-Json $result "Error importing module PSCX"
- }
-
- Try {
- Expand-Archive -Path $src -OutputPath $dest -Force -WhatIf:$check_mode
- } Catch {
- Fail-Json -obj $result -message "Error expanding '$src' to '$dest'! Msg: $($_.Exception.Message)"
- }
-
- If ($recurse) {
- Get-ChildItem -LiteralPath $dest -recurse | Where-Object {$pcx_extensions -contains $_.extension} | ForEach-Object {
- Try {
- Expand-Archive $_.FullName -OutputPath $dest -Force -WhatIf:$check_mode
- } Catch {
- Fail-Json -obj $result -message "Error recursively expanding '$src' to '$dest'! Msg: $($_.Exception.Message)"
- }
- If ($delete_archive) {
- Remove-Item -LiteralPath $_.FullName -Force -WhatIf:$check_mode
- $result.removed = $true
- }
- }
- }
-
- $result.changed = $true
-}
-
-If ($delete_archive){
- try {
- Remove-Item -LiteralPath $src -Recurse -Force -WhatIf:$check_mode
- } catch {
- Fail-Json -obj $result -message "failed to delete archive at '$src': $($_.Exception.Message)"
- }
- $result.removed = $true
-}
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_unzip.py b/lib/ansible/modules/windows/win_unzip.py
deleted file mode 100644
index 5830c61cd8..0000000000
--- a/lib/ansible/modules/windows/win_unzip.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Phil Schwartz <schwartzmx@gmail.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_unzip
-version_added: "2.0"
-short_description: Unzips compressed files and archives on the Windows node
-description:
-- Unzips compressed files and archives.
-- Supports .zip files natively.
-- Supports other formats supported by the Powershell Community Extensions (PSCX) module (basically everything 7zip supports).
-- For non-Windows targets, use the M(unarchive) module instead.
-requirements:
-- PSCX
-options:
- src:
- description:
- - File to be unzipped (provide absolute path).
- type: path
- required: yes
- dest:
- description:
- - Destination of zip file (provide absolute path of directory). If it does not exist, the directory will be created.
- type: path
- required: yes
- delete_archive:
- description:
- - Remove the zip file, after unzipping.
- type: bool
- default: no
- aliases: [ rm ]
- recurse:
- description:
- - Recursively expand zipped files within the src file.
- - Setting to a value of C(yes) requires the PSCX module to be installed.
- type: bool
- default: no
- creates:
- description:
- - If this file or directory exists the specified src will not be extracted.
- type: path
-notes:
-- This module is not really idempotent, it will extract the archive every time, and report a change.
-- For extracting any compression types other than .zip, the PowerShellCommunityExtensions (PSCX) Module is required. This module (in conjunction with PSCX)
- has the ability to recursively unzip files within the src zip file provided and also functionality for many other compression types. If the destination
- directory does not exist, it will be created before unzipping the file. Specifying rm parameter will force removal of the src file after extraction.
-seealso:
-- module: unarchive
-author:
-- Phil Schwartz (@schwartzmx)
-'''
-
-EXAMPLES = r'''
-# This unzips a library that was downloaded with win_get_url, and removes the file after extraction
-# $ ansible -i hosts -m win_unzip -a "src=C:\LibraryToUnzip.zip dest=C:\Lib remove=yes" all
-
-- name: Unzip a bz2 (BZip) file
- win_unzip:
- src: C:\Users\Phil\Logs.bz2
- dest: C:\Users\Phil\OldLogs
- creates: C:\Users\Phil\OldLogs
-
-- name: Unzip gz log
- win_unzip:
- src: C:\Logs\application-error-logs.gz
- dest: C:\ExtractedLogs\application-error-logs
-
-# Unzip .zip file, recursively decompresses the contained .gz files and removes all unneeded compressed files after completion.
-- name: Unzip ApplicationLogs.zip and decompress all GZipped log files
- hosts: all
- gather_facts: no
- tasks:
- - name: Recursively decompress GZ files in ApplicationLogs.zip
- win_unzip:
- src: C:\Downloads\ApplicationLogs.zip
- dest: C:\Application\Logs
- recurse: yes
- delete_archive: yes
-
-- name: Install PSCX
- win_psmodule:
- name: Pscx
- state: present
-'''
-
-RETURN = r'''
-dest:
- description: The provided destination path
- returned: always
- type: str
- sample: C:\ExtractedLogs\application-error-logs
-removed:
- description: Whether the module did remove any files during task run
- returned: always
- type: bool
- sample: true
-src:
- description: The provided source path
- returned: always
- type: str
- sample: C:\Logs\application-error-logs.gz
-'''
diff --git a/lib/ansible/modules/windows/win_user_profile.ps1 b/lib/ansible/modules/windows/win_user_profile.ps1
deleted file mode 100644
index 111abf10ef..0000000000
--- a/lib/ansible/modules/windows/win_user_profile.ps1
+++ /dev/null
@@ -1,163 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2019, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-$spec = @{
- options = @{
- name = @{ type = "str" }
- remove_multiple = @{ type = "bool"; default = $false }
- state = @{ type = "str"; default = "present"; choices = @("absent", "present") }
- username = @{ type = "sid"; }
- }
- required_if = @(
- @("state", "present", @("username")),
- @("state", "absent", @("name", "username"), $true)
- )
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-$module.Result.path = $null
-
-$name = $module.Params.name
-$remove_multiple = $module.Params.remove_multiple
-$state = $module.Params.state
-$username = $module.Params.username
-
-Add-CSharpType -AnsibleModule $module -References @'
-using System;
-using System.Runtime.InteropServices;
-using System.Text;
-
-namespace Ansible.WinUserProfile
-{
- public class NativeMethods
- {
- [DllImport("Userenv.dll", CharSet = CharSet.Unicode)]
- public static extern int CreateProfile(
- [MarshalAs(UnmanagedType.LPWStr)] string pszUserSid,
- [MarshalAs(UnmanagedType.LPWStr)] string pszUserName,
- [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszProfilePath,
- UInt32 cchProfilePath);
-
- [DllImport("Userenv.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool DeleteProfileW(
- [MarshalAs(UnmanagedType.LPWStr)] string lpSidString,
- IntPtr lpProfile,
- IntPtr lpComputerName);
-
- [DllImport("Userenv.dll", SetLastError = true, CharSet = CharSet.Unicode)]
- public static extern bool GetProfilesDirectoryW(
- [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpProfileDir,
- ref UInt32 lpcchSize);
- }
-}
-'@
-
-Function Get-LastWin32ExceptionMessage {
- param([int]$ErrorCode)
- $exp = New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $ErrorCode
- $exp_msg = "{0} (Win32 ErrorCode {1} - 0x{1:X8})" -f $exp.Message, $ErrorCode
- return $exp_msg
-}
-
-Function Get-ExpectedProfilePath {
- param([String]$BaseName)
-
- # Environment.GetFolderPath does not have an enumeration to get the base profile dir, use PInvoke instead
- # and combine with the base name to return back to the user - best efforts
- $profile_path_length = 0
- [Ansible.WinUserProfile.NativeMethods]::GetProfilesDirectoryW($null,
- [ref]$profile_path_length) > $null
-
- $raw_profile_path = New-Object -TypeName System.Text.StringBuilder -ArgumentList $profile_path_length
- $res = [Ansible.WinUserProfile.NativeMethods]::GetProfilesDirectoryW($raw_profile_path,
- [ref]$profile_path_length)
-
- if ($res -eq $false) {
- $msg = Get-LastWin32ExceptionMessage -Error ([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())
- $module.FailJson("Failed to determine profile path with the base name '$BaseName': $msg")
- }
- $profile_path = Join-Path -Path $raw_profile_path.ToString() -ChildPath $BaseName
-
- return $profile_path
-}
-
-$profiles = Get-ChildItem -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
-
-if ($state -eq "absent") {
- if ($null -ne $username) {
- $user_profiles = $profiles | Where-Object { $_.PSChildName -eq $username.Value }
- } else {
- # If the username was not provided, or we are removing a profile for a deleted user, we need to try and find
- # the correct SID to delete. We just verify that the path matches based on the name passed in
- $expected_profile_path = Get-ExpectedProfilePath -BaseName $name
-
- $user_profiles = $profiles | Where-Object {
- $profile_path = (Get-ItemProperty -Path $_.PSPath -Name ProfileImagePath).ProfileImagePath
- $profile_path -eq $expected_profile_path
- }
-
- if ($user_profiles.Length -gt 1 -and -not $remove_multiple) {
- $module.FailJson("Found multiple profiles matching the path '$expected_profile_path', set 'remove_multiple=True' to remove all the profiles for this match")
- }
- }
-
- foreach ($user_profile in $user_profiles) {
- $profile_path = (Get-ItemProperty -Path $user_profile.PSPath -Name ProfileImagePath).ProfileImagePath
- if (-not $module.CheckMode) {
- $res = [Ansible.WinUserProfile.NativeMethods]::DeleteProfileW($user_profile.PSChildName, [IntPtr]::Zero,
- [IntPtr]::Zero)
- if ($res -eq $false) {
- $msg = Get-LastWin32ExceptionMessage -Error ([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())
- $module.FailJson("Failed to delete the profile for $($user_profile.PSChildName): $msg")
- }
- }
-
- # While we may have multiple profiles when the name option was used, it will always be the same path due to
- # how we match name to a profile so setting it mutliple time sis fine
- $module.Result.path = $profile_path
- $module.Result.changed = $true
- }
-} elseif ($state -eq "present") {
- # Now we know the SID, see if the profile already exists
- $user_profile = $profiles | Where-Object { $_.PSChildName -eq $username.Value }
- if ($null -eq $user_profile) {
- # In case a SID was set as the username we still need to make sure the SID is mapped to a valid local account
- try {
- $account_name = $username.Translate([System.Security.Principal.NTAccount])
- } catch [System.Security.Principal.IdentityNotMappedException] {
- $module.FailJson("Fail to map the account '$($username.Value)' to a valid user")
- }
-
- # If the basename was not provided, determine it from the actual username
- if ($null -eq $name) {
- $name = $account_name.Value.Split('\', 2)[-1]
- }
-
- if ($module.CheckMode) {
- $profile_path = Get-ExpectedProfilePath -BaseName $name
- } else {
- $raw_profile_path = New-Object -TypeName System.Text.StringBuilder -ArgumentList 260
- $res = [Ansible.WinUserProfile.NativeMethods]::CreateProfile($username.Value, $name, $raw_profile_path,
- $raw_profile_path.Capacity)
-
- if ($res -ne 0) {
- $exp = [System.Runtime.InteropServices.Marshal]::GetExceptionForHR($res)
- $module.FailJson("Failed to create profile for user '$username': $($exp.Message)")
- }
- $profile_path = $raw_profile_path.ToString()
- }
-
- $module.Result.changed = $true
- $module.Result.path = $profile_path
- } else {
- $module.Result.path = (Get-ItemProperty -Path $user_profile.PSPath -Name ProfileImagePath).ProfileImagePath
- }
-}
-
-$module.ExitJson()
-
diff --git a/lib/ansible/modules/windows/win_user_profile.py b/lib/ansible/modules/windows/win_user_profile.py
deleted file mode 100644
index 264392488c..0000000000
--- a/lib/ansible/modules/windows/win_user_profile.py
+++ /dev/null
@@ -1,113 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2019, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_user_profile
-version_added: '2.8'
-short_description: Manages the Windows user profiles.
-description:
-- Used to create or remove user profiles on a Windows host.
-- This can be used to create a profile before a user logs on or delete a
- profile when removing a user account.
-- A profile can be created for both a local or domain account.
-options:
- name:
- description:
- - Specifies the base name for the profile path.
- - When I(state) is C(present) this is used to create the profile for
- I(username) at a specific path within the profile directory.
- - This cannot be used to specify a path outside of the profile directory
- but rather it specifies a folder(s) within this directory.
- - If a profile for another user already exists at the same path, then a 3
- digit incremental number is appended by Windows automatically.
- - When I(state) is C(absent) and I(username) is not set, then the module
- will remove all profiles that point to the profile path derived by this
- value.
- - This is useful if the account no longer exists but the profile still
- remains.
- type: str
- remove_multiple:
- description:
- - When I(state) is C(absent) and the value for I(name) matches multiple
- profiles the module will fail.
- - Set this value to C(yes) to force the module to delete all the profiles
- found.
- default: no
- type: bool
- state:
- description:
- - Will ensure the profile exists when set to C(present).
- - When creating a profile the I(username) option must be set to a valid
- account.
- - Will remove the profile(s) when set to C(absent).
- - When removing a profile either I(username) must be set to a valid
- account, or I(name) is set to the profile's base name.
- default: present
- choices:
- - absent
- - present
- type: str
- username:
- description:
- - The account name of security identifier (SID) for the profile.
- - This must be set when I(state) is C(present) and must be a valid account
- or the SID of a valid account.
- - When I(state) is C(absent) then this must still be a valid account number
- but the SID can be a deleted user's SID.
-seealso:
-- module: win_user
-- module: win_domain_user
-author:
-- Jordan Borean (@jborean93)
-'''
-
-EXAMPLES = r'''
-- name: Create a profile for an account
- win_user_profile:
- username: ansible-account
- state: present
-
-- name: Create a profile for an account at C:\Users\ansible
- win_user_profile:
- username: ansible-account
- name: ansible
- state: present
-
-- name: Remove a profile for a still valid account
- win_user_profile:
- username: ansible-account
- state: absent
-
-- name: Remove a profile for a deleted account
- win_user_profile:
- name: ansible
- state: absent
-
-- name: Remove a profile for a deleted account based on the SID
- win_user_profile:
- username: S-1-5-21-3233007181-2234767541-1895602582-1305
- state: absent
-
-- name: Remove multiple profiles that exist at the basename path
- win_user_profile:
- name: ansible
- state: absent
- remove_multiple: yes
-'''
-
-RETURN = r'''
-path:
- description: The full path to the profile for the account. This will be null
- if C(state=absent) and no profile was deleted.
- returned: always
- type: str
- sample: C:\Users\ansible
-'''
diff --git a/lib/ansible/modules/windows/win_wait_for_process.ps1 b/lib/ansible/modules/windows/win_wait_for_process.ps1
deleted file mode 100644
index 70ff4bbba4..0000000000
--- a/lib/ansible/modules/windows/win_wait_for_process.ps1
+++ /dev/null
@@ -1,176 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Ansible Project
-# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-#Requires -Module Ansible.ModuleUtils.SID
-
-$spec = @{
- options = @{
- process_name_exact = @{ type='list' }
- process_name_pattern = @{ type='str' }
- pid = @{ type='int'; default=0 }
- owner = @{ type='str' }
- sleep = @{ type='int'; default=1 }
- pre_wait_delay = @{ type='int'; default=0 }
- post_wait_delay = @{ type='int'; default=0 }
- process_min_count = @{ type='int'; default=1 }
- state = @{ type='str'; default='present'; choices=@( 'absent', 'present' ) }
- timeout = @{ type='int'; default=300 }
- }
- mutually_exclusive = @(
- @( 'pid', 'process_name_exact' ),
- @( 'pid', 'process_name_pattern' ),
- @( 'process_name_exact', 'process_name_pattern' )
- )
- required_one_of = @(
- ,@( 'owner', 'pid', 'process_name_exact', 'process_name_pattern' )
- )
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$process_name_exact = $module.Params.process_name_exact
-$process_name_pattern = $module.Params.process_name_pattern
-$process_id = $module.Params.pid # pid is a reserved variable in PowerShell, using process_id instead
-$owner = $module.Params.owner
-$sleep = $module.Params.sleep
-$pre_wait_delay = $module.Params.pre_wait_delay
-$post_wait_delay = $module.Params.post_wait_delay
-$process_min_count = $module.Params.process_min_count
-$state = $module.Params.state
-$timeout = $module.Params.timeout
-
-$module.Result.changed = $false
-$module.Result.elapsed = 0
-$module.Result.matched_processes = @()
-
-# Validate the input
-if ($state -eq "absent" -and $sleep -ne 1) {
- $module.Warn("Parameter 'sleep' has no effect when waiting for a process to stop.")
-}
-
-if ($state -eq "absent" -and $process_min_count -ne 1) {
- $module.Warn("Parameter 'process_min_count' has no effect when waiting for a process to stop.")
-}
-
-if ($owner -and ("IncludeUserName" -notin (Get-Command -Name Get-Process).Parameters.Keys)) {
- $module.FailJson("This version of Powershell does not support filtering processes by 'owner'.")
-}
-
-Function Get-FilteredProcesses {
- [cmdletbinding()]
- Param(
- [String]
- $Owner,
- $ProcessNameExact,
- $ProcessNamePattern,
- [int]
- $ProcessId
- )
-
- $FilteredProcesses = @()
-
- try {
- $Processes = Get-Process -IncludeUserName
- $SupportsUserNames = $true
- } catch [System.Management.Automation.ParameterBindingException] {
- $Processes = Get-Process
- $SupportsUserNames = $false
- }
-
- foreach ($Process in $Processes) {
-
- # If a process name was specified in the filter, validate that here.
- if ($ProcessNamePattern) {
- if ($Process.ProcessName -notmatch $ProcessNamePattern) {
- continue
- }
- }
-
- # If a process name was specified in the filter, validate that here.
- if ($ProcessNameExact -is [Array]) {
- if ($ProcessNameExact -notcontains $Process.ProcessName) {
- continue
- }
- } elseif ($ProcessNameExact) {
- if ($ProcessNameExact -ne $Process.ProcessName) {
- continue
- }
- }
-
- # If a PID was specified in the filter, validate that here.
- if ($ProcessId -and $ProcessId -ne 0) {
- if ($ProcessId -ne $Process.Id) {
- continue
- }
- }
-
- # If an owner was specified in the filter, validate that here.
- if ($Owner) {
- if (-not $Process.UserName) {
- continue
- } elseif ((Convert-ToSID($Owner)) -ne (Convert-ToSID($Process.UserName))) { # NOTE: This is rather expensive
- continue
- }
- }
-
- if ($SupportsUserNames -eq $true) {
- $FilteredProcesses += @{ name = $Process.ProcessName; pid = $Process.Id; owner = $Process.UserName }
- } else {
- $FilteredProcesses += @{ name = $Process.ProcessName; pid = $Process.Id }
- }
- }
-
- return ,$FilteredProcesses
-}
-
-$module_start = Get-Date
-Start-Sleep -Seconds $pre_wait_delay
-
-if ($state -eq "present" ) {
-
- # Wait for a process to start
- do {
-
- $Processes = Get-FilteredProcesses -Owner $owner -ProcessNameExact $process_name_exact -ProcessNamePattern $process_name_pattern -ProcessId $process_id
- $module.Result.matched_processes = $Processes
-
- if ($Processes.count -ge $process_min_count) {
- break
- }
-
- if (((Get-Date) - $module_start).TotalSeconds -gt $timeout) {
- $module.Result.elapsed = ((Get-Date) - $module_start).TotalSeconds
- $module.FailJson("Timed out while waiting for process(es) to start")
- }
-
- Start-Sleep -Seconds $sleep
-
- } while ($true)
-
-} elseif ($state -eq "absent") {
-
- # Wait for a process to stop
- $Processes = Get-FilteredProcesses -Owner $owner -ProcessNameExact $process_name_exact -ProcessNamePattern $process_name_pattern -ProcessId $process_id
- $module.Result.matched_processes = $Processes
-
- if ($Processes.count -gt 0 ) {
- try {
- # This may randomly fail when used on specially protected processes (think: svchost)
- Wait-Process -Id $Processes.pid -Timeout $timeout
- } catch [System.TimeoutException] {
- $module.Result.elapsed = ((Get-Date) - $module_start).TotalSeconds
- $module.FailJson("Timeout while waiting for process(es) to stop")
- }
- }
-
-}
-
-Start-Sleep -Seconds $post_wait_delay
-$module.Result.elapsed = ((Get-Date) - $module_start).TotalSeconds
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_wait_for_process.py b/lib/ansible/modules/windows/win_wait_for_process.py
deleted file mode 100644
index a26e2be5fe..0000000000
--- a/lib/ansible/modules/windows/win_wait_for_process.py
+++ /dev/null
@@ -1,134 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub, actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_wait_for_process
-version_added: '2.7'
-short_description: Waits for a process to exist or not exist before continuing.
-description:
-- Waiting for a process to start or stop.
-- This is useful when Windows services behave poorly and do not enumerate external dependencies in their manifest.
-options:
- process_name_exact:
- description:
- - The name of the process(es) for which to wait. The name of the process(es) should not include the file extension suffix.
- type: list
- process_name_pattern:
- description:
- - RegEx pattern matching desired process(es).
- type: str
- sleep:
- description:
- - Number of seconds to sleep between checks.
- - Only applies when waiting for a process to start. Waiting for a process to start
- does not have a native non-polling mechanism. Waiting for a stop uses native PowerShell
- and does not require polling.
- type: int
- default: 1
- process_min_count:
- description:
- - Minimum number of process matching the supplied pattern to satisfy C(present) condition.
- - Only applies to C(present).
- type: int
- default: 1
- pid:
- description:
- - The PID of the process.
- type: int
- owner:
- description:
- - The owner of the process.
- - Requires PowerShell version 4.0 or newer.
- type: str
- pre_wait_delay:
- description:
- - Seconds to wait before checking processes.
- type: int
- default: 0
- post_wait_delay:
- description:
- - Seconds to wait after checking for processes.
- type: int
- default: 0
- state:
- description:
- - When checking for a running process C(present) will block execution
- until the process exists, or until the timeout has been reached.
- C(absent) will block execution until the process no longer exists,
- or until the timeout has been reached.
- - When waiting for C(present), the module will return changed only if
- the process was not present on the initial check but became present on
- subsequent checks.
- - If, while waiting for C(absent), new processes matching the supplied
- pattern are started, these new processes will not be included in the
- action.
- type: str
- default: present
- choices: [ absent, present ]
- timeout:
- description:
- - The maximum number of seconds to wait for a for a process to start or stop
- before erroring out.
- type: int
- default: 300
-seealso:
-- module: wait_for
-- module: win_wait_for
-author:
-- Charles Crossan (@crossan007)
-'''
-
-EXAMPLES = r'''
-- name: Wait 300 seconds for all Oracle VirtualBox processes to stop. (VBoxHeadless, VirtualBox, VBoxSVC)
- win_wait_for_process:
- process_name_pattern: 'v(irtual)?box(headless|svc)?'
- state: absent
- timeout: 500
-
-- name: Wait 300 seconds for 3 instances of cmd to start, waiting 5 seconds between each check
- win_wait_for_process:
- process_name_exact: cmd
- state: present
- timeout: 500
- sleep: 5
- process_min_count: 3
-'''
-
-RETURN = r'''
-elapsed:
- description: The elapsed seconds between the start of poll and the end of the module.
- returned: always
- type: float
- sample: 3.14159265
-matched_processes:
- description: List of matched processes (either stopped or started).
- returned: always
- type: complex
- contains:
- name:
- description: The name of the matched process.
- returned: always
- type: str
- sample: svchost
- owner:
- description: The owner of the matched process.
- returned: when supported by PowerShell
- type: str
- sample: NT AUTHORITY\SYSTEM
- pid:
- description: The PID of the matched process.
- returned: always
- type: int
- sample: 7908
-'''
diff --git a/lib/ansible/modules/windows/win_wakeonlan.ps1 b/lib/ansible/modules/windows/win_wakeonlan.ps1
deleted file mode 100644
index f14889534d..0000000000
--- a/lib/ansible/modules/windows/win_wakeonlan.ps1
+++ /dev/null
@@ -1,52 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2017, Dag Wieers (@dagwieers) <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#AnsibleRequires -CSharpUtil Ansible.Basic
-
-$spec = @{
- options = @{
- mac = @{ type='str'; required=$true }
- broadcast = @{ type='str'; default='255.255.255.255' }
- port = @{ type='int'; default=7 }
- }
- supports_check_mode = $true
-}
-
-$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
-
-$module.Result.changed = $false
-
-$mac = $module.Params.mac
-$mac_orig = $module.Params.mac
-$broadcast = $module.Params.broadcast
-$port = $module.Params.port
-
-$broadcast = [Net.IPAddress]::Parse($broadcast)
-
-# Remove possible separator from MAC address
-if ($mac.Length -eq (12 + 5)) {
- $mac = $mac.Replace($mac.Substring(2, 1), "")
-}
-
-# If we don't end up with 12 hexadecimal characters, fail
-if ($mac.Length -ne 12) {
- $module.FailJson("Incorrect MAC address: $mac_orig")
-}
-
-# Create payload for magic packet
-# TODO: Catch possible conversion errors
-$target = 0,2,4,6,8,10 | ForEach-Object { [convert]::ToByte($mac.Substring($_, 2), 16) }
-$data = (,[byte]255 * 6) + ($target * 20)
-
-# Broadcast payload to network
-$udpclient = new-Object System.Net.Sockets.UdpClient
-if (-not $module.CheckMode) {
- $udpclient.Connect($broadcast, $port)
- [void] $udpclient.Send($data, 102)
-}
-
-$module.Result.changed = $true
-
-$module.ExitJson()
diff --git a/lib/ansible/modules/windows/win_wakeonlan.py b/lib/ansible/modules/windows/win_wakeonlan.py
deleted file mode 100644
index 60439624af..0000000000
--- a/lib/ansible/modules/windows/win_wakeonlan.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2017, Dag Wieers <dag@wieers.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_wakeonlan
-version_added: '2.4'
-short_description: Send a magic Wake-on-LAN (WoL) broadcast packet
-description:
-- The C(win_wakeonlan) module sends magic Wake-on-LAN (WoL) broadcast packets.
-- For non-Windows targets, use the M(wakeonlan) module instead.
-options:
- mac:
- description:
- - MAC address to send Wake-on-LAN broadcast packet for.
- type: str
- required: yes
- broadcast:
- description:
- - Network broadcast address to use for broadcasting magic Wake-on-LAN packet.
- type: str
- default: 255.255.255.255
- port:
- description:
- - UDP port to use for magic Wake-on-LAN packet.
- type: int
- default: 7
-todo:
-- Does not have SecureOn password support
-notes:
-- This module sends a magic packet, without knowing whether it worked. It always report a change.
-- Only works if the target system was properly configured for Wake-on-LAN (in the BIOS and/or the OS).
-- Some BIOSes have a different (configurable) Wake-on-LAN boot order (i.e. PXE first).
-seealso:
-- module: wakeonlan
-author:
-- Dag Wieers (@dagwieers)
-'''
-
-EXAMPLES = r'''
-- name: Send a magic Wake-on-LAN packet to 00:00:5E:00:53:66
- win_wakeonlan:
- mac: 00:00:5E:00:53:66
- broadcast: 192.0.2.23
-
-- name: Send a magic Wake-On-LAN packet on port 9 to 00-00-5E-00-53-66
- win_wakeonlan:
- mac: 00-00-5E-00-53-66
- port: 9
- delegate_to: remote_system
-'''
-
-RETURN = r'''
-# Default return values
-'''
diff --git a/lib/ansible/modules/windows/win_webpicmd.ps1 b/lib/ansible/modules/windows/win_webpicmd.ps1
deleted file mode 100644
index c2d1b7ca71..0000000000
--- a/lib/ansible/modules/windows/win_webpicmd.ps1
+++ /dev/null
@@ -1,116 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2015, Peter Mounce <public@neverrunwithscissors.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-
-$ErrorActionPreference = "Stop"
-
-Function Find-Command
-{
- [CmdletBinding()]
- param(
- [Parameter(Mandatory=$true, Position=0)] [string] $command
- )
- $installed = get-command $command -erroraction Ignore
- write-verbose "$installed"
- if ($installed)
- {
- return $installed
- }
- return $null
-}
-
-Function Find-WebPiCmd
-{
- [CmdletBinding()]
- param()
- $p = Find-Command "webpicmd.exe"
- if ($null -ne $p)
- {
- return $p
- }
- $a = Find-Command "c:\programdata\chocolatey\bin\webpicmd.exe"
- if ($null -ne $a)
- {
- return $a
- }
- Throw "webpicmd.exe is not installed. It must be installed (use chocolatey)"
-}
-
-Function Test-IsInstalledFromWebPI
-{
- [CmdletBinding()]
-
- param(
- [Parameter(Mandatory=$true, Position=0)]
- [string]$package
- )
-
- $cmd = "$executable /list /listoption:installed"
- $results = invoke-expression $cmd
-
- if ($LastExitCode -ne 0)
- {
- $result.webpicmd_error_cmd = $cmd
- $result.webpicmd_error_log = "$results"
-
- Throw "Error checking installation status for $package"
- }
- Write-Verbose "$results"
-
- if ($results -match "^$package\s+")
- {
- return $true
- }
-
- return $false
-}
-
-Function Install-WithWebPICmd
-{
- [CmdletBinding()]
-
- param(
- [Parameter(Mandatory=$true, Position=0)]
- [string]$package
- )
-
- $cmd = "$executable /install /products:$package /accepteula /suppressreboot"
-
- $results = invoke-expression $cmd
-
- if ($LastExitCode -ne 0)
- {
- $result.webpicmd_error_cmd = $cmd
- $result.webpicmd_error_log = "$results"
- Throw "Error installing $package"
- }
-
- write-verbose "$results"
-
- if ($results -match "Install of Products: SUCCESS")
- {
- $result.changed = $true
- }
-}
-
-$result = @{
- changed = $false
-}
-
-$params = Parse-Args $args
-
-$package = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
-
-Try {
- $script:executable = Find-WebPiCmd
- if ((Test-IsInstalledFromWebPI -package $package) -eq $false) {
- Install-WithWebPICmd -package $package
- }
-
- Exit-Json $result
-} Catch {
- Fail-Json $result $_.Exception.Message
-}
diff --git a/lib/ansible/modules/windows/win_webpicmd.py b/lib/ansible/modules/windows/win_webpicmd.py
deleted file mode 100644
index fc0663b304..0000000000
--- a/lib/ansible/modules/windows/win_webpicmd.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2015, Peter Mounce <public@neverrunwithscissors.com>
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_webpicmd
-version_added: "2.0"
-short_description: Installs packages using Web Platform Installer command-line
-description:
- - Installs packages using Web Platform Installer command-line
- (U(http://www.iis.net/learn/install/web-platform-installer/web-platform-installer-v4-command-line-webpicmdexe-rtw-release)).
- - Must be installed and present in PATH (see M(win_chocolatey) module; 'webpicmd' is the package name, and you must install 'lessmsi' first too)?
- - Install IIS first (see M(win_feature) module).
-notes:
- - Accepts EULAs and suppresses reboot - you will need to check manage reboots yourself (see M(win_reboot) module)
-options:
- name:
- description:
- - Name of the package to be installed.
- type: str
- required: yes
-seealso:
-- module: win_package
-author:
-- Peter Mounce (@petemounce)
-'''
-
-EXAMPLES = r'''
-- name: Install URLRewrite2.
- win_webpicmd:
- name: URLRewrite2
-'''
diff --git a/lib/ansible/modules/windows/win_xml.ps1 b/lib/ansible/modules/windows/win_xml.ps1
deleted file mode 100644
index d051a3f67d..0000000000
--- a/lib/ansible/modules/windows/win_xml.ps1
+++ /dev/null
@@ -1,265 +0,0 @@
-#!powershell
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-#Requires -Module Ansible.ModuleUtils.Legacy
-#Requires -Module Ansible.ModuleUtils.Backup
-
-Set-StrictMode -Version 2
-
-function Copy-Xml($dest, $src, $xmlorig) {
- if ($src.get_NodeType() -eq "Text") {
- $dest.set_InnerText($src.get_InnerText())
- }
-
- if ($src.get_HasAttributes()) {
- foreach ($attr in $src.get_Attributes()) {
- $dest.SetAttribute($attr.get_Name(), $attr.get_Value())
- }
- }
-
- if ($src.get_HasChildNodes()) {
- foreach ($childnode in $src.get_ChildNodes()) {
- if ($childnode.get_NodeType() -eq "Element") {
- $newnode = $xmlorig.CreateElement($childnode.get_Name(), $xmlorig.get_DocumentElement().get_NamespaceURI())
- Copy-Xml -dest $newnode -src $childnode -xmlorig $xmlorig
- $dest.AppendChild($newnode) | Out-Null
- } elseif ($childnode.get_NodeType() -eq "Text") {
- $dest.set_InnerText($childnode.get_InnerText())
- }
- }
- }
-}
-
-function Compare-XmlDocs($actual, $expected) {
- if ($actual.get_Name() -ne $expected.get_Name()) {
- throw "Actual name not same as expected: actual=" + $actual.get_Name() + ", expected=" + $expected.get_Name()
- }
- ##attributes...
-
- if (($actual.get_NodeType() -eq "Element") -and ($expected.get_NodeType() -eq "Element")) {
- if ($actual.get_HasAttributes() -and $expected.get_HasAttributes()) {
- if ($actual.get_Attributes().Count -ne $expected.get_Attributes().Count) {
- throw "attribute mismatch for actual=" + $actual.get_Name()
- }
- for ($i=0;$i -lt $expected.get_Attributes().Count; $i =$i+1) {
- if ($expected.get_Attributes()[$i].get_Name() -ne $actual.get_Attributes()[$i].get_Name()) {
- throw "attribute name mismatch for actual=" + $actual.get_Name()
- }
- if ($expected.get_Attributes()[$i].get_Value() -ne $actual.get_Attributes()[$i].get_Value()) {
- throw "attribute value mismatch for actual=" + $actual.get_Name()
- }
- }
- }
-
- if (($actual.get_HasAttributes() -and !$expected.get_HasAttributes()) -or (!$actual.get_HasAttributes() -and $expected.get_HasAttributes())) {
- throw "attribute presence mismatch for actual=" + $actual.get_Name()
- }
- }
-
- ##children
- if ($expected.get_ChildNodes().Count -ne $actual.get_ChildNodes().Count) {
- throw "child node mismatch. for actual=" + $actual.get_Name()
- }
-
- for ($i=0;$i -lt $expected.get_ChildNodes().Count; $i =$i+1) {
- if (-not $actual.get_ChildNodes()[$i]) {
- throw "actual missing child nodes. for actual=" + $actual.get_Name()
- }
- Compare-XmlDocs $expected.get_ChildNodes()[$i] $actual.get_ChildNodes()[$i]
- }
-
- if ($expected.get_InnerText()) {
- if ($expected.get_InnerText() -ne $actual.get_InnerText()) {
- throw "inner text mismatch for actual=" + $actual.get_Name()
- }
- }
- elseif ($actual.get_InnerText()) {
- throw "actual has inner text but expected does not for actual=" + $actual.get_Name()
- }
-}
-
-
-function Save-ChangedXml($xmlorig, $result, $message, $check_mode, $backup) {
- $result.changed = $true
- if (-Not $check_mode) {
- if ($backup) {
- $result.backup_file = Backup-File -path $dest -WhatIf:$check_mode
- # Ensure backward compatibility (deprecate in future)
- $result.backup = $result.backup_file
- }
- $xmlorig.Save($dest)
- $result.msg = $message
- } else {
- $result.msg += " check mode"
- }
-}
-
-$params = Parse-Args $args -supports_check_mode $true
-$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
-
-$debug_level = Get-AnsibleParam -obj $params -name "_ansible_verbosity" -type "int"
-$debug = $debug_level -gt 2
-
-$dest = Get-AnsibleParam $params "path" -type "path" -FailIfEmpty $true -aliases "dest", "file"
-$fragment = Get-AnsibleParam $params "fragment" -type "str" -aliases "xmlstring"
-$xpath = Get-AnsibleParam $params "xpath" -type "str" -FailIfEmpty $true
-$backup = Get-AnsibleParam $params "backup" -type "bool" -Default $false
-$type = Get-AnsibleParam $params "type" -type "str" -Default "element" -ValidateSet "element", "attribute", "text"
-$attribute = Get-AnsibleParam $params "attribute" -type "str" -FailIfEmpty ($type -eq "attribute")
-$state = Get-AnsibleParam $params "state" -type "str" -Default "present"
-$count = Get-AnsibleParam $params "count" -type "bool" -Default $false
-
-$result = @{
- changed = $false
-}
-
-If (-Not (Test-Path -Path $dest -PathType Leaf)){
- Fail-Json $result "Specified path $dest does not exist or is not a file."
-}
-
-$xmlorig = New-Object -TypeName System.Xml.XmlDocument
-$xmlorig.XmlResolver = $null
-Try {
- $xmlorig.Load($dest)
-}
-Catch {
- Fail-Json $result "Failed to parse file at '$dest' as an XML document: $($_.Exception.Message)"
-}
-
-$namespaceMgr = New-Object System.Xml.XmlNamespaceManager $xmlorig.NameTable
-$namespace = $xmlorig.DocumentElement.NamespaceURI
-$localname = $xmlorig.DocumentElement.LocalName
-
-$namespaceMgr.AddNamespace($xmlorig.$localname.SchemaInfo.Prefix, $namespace)
-
-$nodeList = $xmlorig.SelectNodes($xpath, $namespaceMgr)
-$nodeListCount = $nodeList.get_Count()
-if ($count) {
- $result.count = $nodeListCount
- if (-not $fragment) {
- Exit-Json $result
- }
-}
-## Exit early if xpath did not match any nodes
-if ($nodeListCount -eq 0) {
- $result.msg = "The supplied xpath did not match any nodes. If this is unexpected, check your xpath is valid for the xml file at supplied path."
- Exit-Json $result
-}
-
-$changed = $false
-$result.msg = "not changed"
-
-if ($type -eq "element") {
- if ($state -eq "absent") {
- foreach ($node in $nodeList) {
- # there are some nodes that match xpath, delete without comparing them to fragment
- if (-Not $check_mode) {
- $removedNode = $node.get_ParentNode().RemoveChild($node)
- $changed = $true
- if ($debug) {
- $result.removed += $result.removed + $removedNode.get_OuterXml()
- }
- }
- }
- } else { # state -eq 'present'
- $xmlfragment = $null
- Try {
- $xmlfragment = [xml]$fragment
- } Catch {
- Fail-Json $result "Failed to parse fragment as XML: $($_.Exception.Message)"
- }
-
- foreach ($node in $nodeList) {
- $candidate = $xmlorig.CreateElement($xmlfragment.get_DocumentElement().get_Name(), $xmlorig.get_DocumentElement().get_NamespaceURI())
- Copy-Xml -dest $candidate -src $xmlfragment.DocumentElement -xmlorig $xmlorig
-
- if ($node.get_NodeType() -eq "Document") {
- $node = $node.get_DocumentElement()
- }
- $elements = $node.get_ChildNodes()
- [bool]$present = $false
- [bool]$changed = $false
- $element_count = $elements.get_Count()
- $nstatus = "node: " + $node.get_Value() + " element: " + $elements.get_OuterXml() + " Element count is $element_count"
- Add-Warning $result $nstatus
- if ($elements.get_Count()) {
- if ($debug) {
- $err = @()
- $result.err = {$err}.Invoke()
- }
- foreach ($element in $elements) {
- $estatus = "element is " + $element.get_OuterXml()
- Add-Warning $result $estatus
- try {
- Compare-XmlDocs $candidate $element
- $present = $true
- break
- } catch {
- if ($debug) {
- $result.err.Add($_.Exception.ToString())
- }
- }
- }
- if (-Not $present -and ($state -eq "present")) {
- [void]$node.AppendChild($candidate)
- $result.msg = $result.msg + "xml added "
- $changed = $true
- }
- }
- }
- }
-} elseif ($type -eq "text") {
- foreach ($node in $nodeList) {
- if ($node.get_InnerText() -ne $fragment) {
- $node.set_InnerText($fragment)
- $changed = $true
- }
- }
-} elseif ($type -eq "attribute") {
- foreach ($node in $nodeList) {
- if ($state -eq 'present') {
- if ($node.NodeType -eq 'Attribute') {
- if ($node.Name -eq $attribute -and $node.Value -ne $fragment ) {
- # this is already the attribute with the right name, so just set its value to match fragment
- $node.Value = $fragment
- $changed = $true
- }
- } else { # assume NodeType is Element
- if ($node.$attribute -ne $fragment) {
- if (!$node.HasAttribute($attribute)) { # add attribute to Element if missing
- $node.SetAttributeNode($attribute, $xmlorig.get_DocumentElement().get_NamespaceURI())
- }
- #set the attribute into the element
- $node.SetAttribute($attribute, $fragment)
- $changed = $true
- }
- }
- } elseif ($state -eq 'absent') {
- if ($node.NodeType -eq 'Attribute') {
- $attrNode = [System.Xml.XmlAttribute]$node
- $parent = $attrNode.OwnerElement
- $parent.RemoveAttribute($attribute)
- $changed = $true
- } else { # element node processing
- if ($node.Name -eq $attribute ) { # note not caring about the state of 'fragment' at this point
- $node.RemoveAttribute($attribute)
- $changed = $true
- }
- }
- } else {
- Add-Warning $result "Unexpected state when processing attribute $($attribute), add was $add, state was $state"
- }
- }
-}
-if ($changed) {
- if ($state -eq "absent") {
- $summary = "$type removed"
- } else {
- $summary = "$type changed"
- }
- Save-ChangedXml -xmlorig $xmlorig -result $result -message $summary -check_mode $check_mode -backup $backup
-}
-
-Exit-Json $result
diff --git a/lib/ansible/modules/windows/win_xml.py b/lib/ansible/modules/windows/win_xml.py
deleted file mode 100644
index a503df81d8..0000000000
--- a/lib/ansible/modules/windows/win_xml.py
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-
-# Copyright: (c) 2018, Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-# this is a windows documentation stub. actual code lives in the .ps1
-# file of the same name
-
-ANSIBLE_METADATA = {'metadata_version': '1.1',
- 'status': ['preview'],
- 'supported_by': 'community'}
-
-DOCUMENTATION = r'''
----
-module: win_xml
-version_added: "2.7"
-short_description: Manages XML file content on Windows hosts
-description:
- - Manages XML nodes, attributes and text, using xpath to select which xml nodes need to be managed.
- - XML fragments, formatted as strings, are used to specify the desired state of a part or parts of XML files on remote Windows servers.
- - For non-Windows targets, use the M(xml) module instead.
-options:
- attribute:
- description:
- - The attribute name if the type is 'attribute'.
- - Required if C(type=attribute).
- type: str
- count:
- description:
- - When set to C(yes), return the number of nodes matched by I(xpath).
- type: bool
- default: false
- version_added: 2.9
- backup:
- description:
- - Determine whether a backup should be created.
- - When set to C(yes), create a backup file including the timestamp information
- so you can get the original file back if you somehow clobbered it incorrectly.
- type: bool
- default: no
- fragment:
- description:
- - The string representation of the XML fragment expected at xpath. Since ansible 2.9 not required when I(state=absent), or when I(count=yes).
- type: str
- required: false
- aliases: [ xmlstring ]
- path:
- description:
- - Path to the file to operate on.
- type: path
- required: true
- aliases: [ dest, file ]
- state:
- description:
- - Set or remove the nodes (or attributes) matched by I(xpath).
- type: str
- default: present
- choices: [ present, absent ]
- version_added: 2.9
- type:
- description:
- - The type of XML node you are working with.
- type: str
- required: yes
- default: element
- choices: [ attribute, element, text ]
- xpath:
- description:
- - Xpath to select the node or nodes to operate on.
- type: str
- required: true
-author:
- - Richard Levenberg (@richardcs)
- - Jon Hawkesworth (@jhawkesworth)
-notes:
- - Only supports operating on xml elements, attributes and text.
- - Namespace, processing-instruction, command and document node types cannot be modified with this module.
-seealso:
- - module: xml
- description: XML manipulation for Posix hosts.
- - name: w3shools XPath tutorial
- description: A useful tutorial on XPath
- link: https://www.w3schools.com/xml/xpath_intro.asp
-'''
-
-EXAMPLES = r'''
-- name: Apply our filter to Tomcat web.xml
- win_xml:
- path: C:\apache-tomcat\webapps\myapp\WEB-INF\web.xml
- fragment: '<filter><filter-name>MyFilter</filter-name><filter-class>com.example.MyFilter</filter-class></filter>'
- xpath: '/*'
-
-- name: Apply sslEnabledProtocols to Tomcat's server.xml
- win_xml:
- path: C:\Tomcat\conf\server.xml
- xpath: '//Server/Service[@name="Catalina"]/Connector[@port="9443"]'
- attribute: 'sslEnabledProtocols'
- fragment: 'TLSv1,TLSv1.1,TLSv1.2'
- type: attribute
-
-- name: remove debug configuration nodes from nlog.conf
- win_xml:
- path: C:\IISApplication\nlog.conf
- xpath: /nlog/rules/logger[@name="debug"]/descendant::*
- state: absent
-
-- name: count configured connectors in Tomcat's server.xml
- win_xml:
- path: C:\Tomcat\conf\server.xml
- xpath: //Server/Service/Connector
- count: yes
- register: connector_count
-
-- name: show connector count
- debug:
- msg="Connector count is {{connector_count.count}}"
-
-- name: ensure all lang=en attributes to lang=nl
- win_xml:
- path: C:\Data\Books.xml
- xpath: //@[lang="en"]
- attribute: lang
- fragment: nl
- type: attribute
-
-'''
-
-RETURN = r'''
-backup_file:
- description: Name of the backup file that was created.
- returned: if backup=yes
- type: str
- sample: C:\Path\To\File.txt.11540.20150212-220915.bak
-count:
- description: Number of nodes matched by xpath.
- returned: if count=yes
- type: int
- sample: 33
-msg:
- description: What was done.
- returned: always
- type: str
- sample: "xml added"
-err:
- description: XML comparison exceptions.
- returned: always, for type element and -vvv or more
- type: list
- sample: attribute mismatch for actual=string
-'''
diff --git a/lib/ansible/plugins/lookup/laps_password.py b/lib/ansible/plugins/lookup/laps_password.py
deleted file mode 100644
index f48e76a06c..0000000000
--- a/lib/ansible/plugins/lookup/laps_password.py
+++ /dev/null
@@ -1,358 +0,0 @@
-# (c) 2019 Ansible Project
-# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
-
-from __future__ import (absolute_import, division, print_function)
-__metaclass__ = type
-
-DOCUMENTATION = """
-lookup: laps_password
-author: Jordan Borean (@jborean93)
-version_added: "2.8"
-short_description: Retrieves the LAPS password for a server.
-description:
-- This lookup returns the LAPS password set for a server from the Active Directory database.
-- See U(https://github.com/jborean93/ansible-lookup-laps_password) for more information around installing
- pre-requisites and testing.
-options:
- _terms:
- description:
- - The host name to retrieve the LAPS password for.
- - This is the C(Common Name (CN)) of the host.
- required: True
- type: str
- allow_plaintext:
- description:
- - When set to C(yes), will allow traffic to be sent unencrypted.
- - It is highly recommended to not touch this to avoid any credentials being exposed over the network.
- - Use C(scheme=ldaps), C(auth=gssapi), or C(start_tls=yes) to ensure the traffic is encrypted.
- default: no
- type: bool
- auth:
- description:
- - The type of authentication to use when connecting to the Active Directory server
- - When using C(simple), the I(username) and I(password) options must be set. If not using C(scheme=ldaps) or
- C(start_tls=True) then these credentials are exposed in plaintext in the network traffic.
- - It is recommended ot use C(gssapi) as it will encrypt the traffic automatically.
- - When using C(gssapi), run C(kinit) before running Ansible to get a valid Kerberos ticket.
- - You cannot use C(gssapi) when either C(scheme=ldaps) or C(start_tls=True) is set.
- choices:
- - simple
- - gssapi
- default: gssapi
- type: str
- ca_cert:
- description:
- - The path to a CA certificate PEM file to use for certificate validation.
- - Certificate validation is used when C(scheme=ldaps) or C(start_tls=yes).
- - This may fail on hosts with an older OpenLDAP install like MacOS, this will have to be updated before
- reinstalling python-ldap to get working again.
- type: str
- aliases: [ cacert_file ]
- domain:
- description:
- - The domain to search in to retrieve the LAPS password.
- - This could either be a Windows domain name visible to the Ansible controller from DNS or a specific domain
- controller FQDN.
- - Supports either just the domain/host name or an explicit LDAP URI with the domain/host already filled in.
- - If the URI is set, I(port) and I(scheme) are ignored.
- required: True
- type: str
- password:
- description:
- - The password for C(username).
- - Required when C(username) is set.
- type: str
- port:
- description:
- - The LDAP port to communicate over.
- - If I(kdc) is already an LDAP URI then this is ignored.
- type: int
- scheme:
- description:
- - The LDAP scheme to use.
- - When using C(ldap), it is recommended to set C(auth=gssapi), or C(start_tls=yes), otherwise traffic will be in
- plaintext.
- - The Active Directory host must be configured for C(ldaps) with a certificate before it can be used.
- - If I(kdc) is already an LDAP URI then this is ignored.
- choices:
- - ldap
- - ldaps
- default: ldap
- search_base:
- description:
- - Changes the search base used when searching for the host in Active Directory.
- - Will default to search in the C(defaultNamingContext) of the Active Directory server.
- - If multiple matches are found then a more explicit search_base is required so only 1 host is found.
- - If searching a larger Active Directory database, it is recommended to narrow the search_base for performance
- reasons.
- type: str
- start_tls:
- description:
- - When C(scheme=ldap), will use the StartTLS extension to encrypt traffic sent over the wire.
- - This requires the Active Directory to be set up with a certificate that supports StartTLS.
- - This is ignored when C(scheme=ldaps) as the traffic is already encrypted.
- type: bool
- default: no
- username:
- description:
- - Required when using C(auth=simple).
- - The username to authenticate with.
- - Recommended to use the username in the UPN format, e.g. C(username@DOMAIN.COM).
- - This is required when C(auth=simple) and is not supported when C(auth=gssapi).
- - Call C(kinit) outside of Ansible if C(auth=gssapi) is required.
- type: str
- validate_certs:
- description:
- - When using C(scheme=ldaps) or C(start_tls=yes), this controls the certificate validation behaviour.
- - C(demand) will fail if no certificate or an invalid certificate is provided.
- - C(try) will fail for invalid certificates but will continue if no certificate is provided.
- - C(allow) will request and check a certificate but will continue even if it is invalid.
- - C(never) will not request a certificate from the server so no validation occurs.
- default: demand
- choices:
- - never
- - allow
- - try
- - demand
- type: str
-requirements:
-- python-ldap
-notes:
-- If a host was found but had no LAPS password attribute C(ms-Mcs-AdmPwd), the lookup will fail.
-- Due to the sensitive nature of the data travelling across the network, it is highly recommended to run with either
- C(auth=gssapi), C(scheme=ldaps), or C(start_tls=yes).
-- Failing to run with one of the above settings will result in the account credentials as well as the LAPS password to
- be sent in plaintext.
-- Some scenarios may not work when running on a host with an older OpenLDAP install like MacOS. It is recommended to
- install the latest OpenLDAP version and build python-ldap against this, see
- U(https://keathmilligan.net/python-ldap-and-macos) for more information.
-"""
-
-EXAMPLES = """
-# This isn't mandatory but it is a way to call kinit from within Ansible before calling the lookup
-- name: call kinit to retrieve Kerberos token
- expect:
- command: kinit username@ANSIBLE.COM
- responses:
- (?i)password: SecretPass1
- no_log: True
-
-- name: Get the LAPS password using Kerberos auth, relies on kinit already being called
- set_fact:
- ansible_password: "{{ lookup('laps_password', 'SERVER', domain='dc01.ansible.com') }}"
-
-- name: Specific the domain host using an explicit LDAP URI
- set_fact:
- ansible_password: "{{ lookup('laps_password', 'SERVER', domain='ldap://ansible.com:389') }}"
-
-- name: Use Simple auth over LDAPS
- set_fact:
- ansible_password: "{{ lookup('laps_password', 'server',
- domain='dc01.ansible.com',
- auth='simple',
- scheme='ldaps',
- username='username@ANSIBLE.COM',
- password='SuperSecret123') }}"
-
-- name: Use Simple auth with LDAP and StartTLS
- set_fact:
- ansible_password: "{{ lookup('laps_password', 'app01',
- domain='dc01.ansible.com',
- auth='simple',
- start_tls=True,
- username='username@ANSIBLE.COM',
- password='SuperSecret123') }}"
-
-- name: Narrow down the search base to a an OU
- set_fact:
- ansible_password: "{{ lookup('laps_password', 'sql10',
- domain='dc01.ansible.com',
- search_base='OU=Databases,DC=ansible,DC=com') }}"
-
-- name: Set certificate file to use when validating the TLS certificate
- set_fact:
- ansible_password: "{{ lookup('laps_password', 'windows-pc',
- domain='dc01.ansible.com',
- start_tls=True,
- ca_cert='/usr/local/share/certs/ad.pem') }}"
-"""
-
-RETURN = """
-_raw:
- description:
- - The LAPS password(s) for the host(s) requested.
- type: str
-"""
-
-import os
-import traceback
-
-from ansible.errors import AnsibleLookupError
-from ansible.module_utils._text import to_bytes, to_native, to_text
-from ansible.module_utils.basic import missing_required_lib
-from ansible.plugins.lookup import LookupBase
-
-LDAP_IMP_ERR = None
-try:
- import ldap
- import ldapurl
- HAS_LDAP = True
-except ImportError:
- LDAP_IMP_ERR = traceback.format_exc()
- HAS_LDAP = False
-
-
-def get_laps_password(conn, cn, search_base):
- search_filter = u"(&(objectClass=computer)(CN=%s))" % to_text(cn)
-
- ldap_results = conn.search_s(to_text(search_base), ldap.SCOPE_SUBTREE, search_filter,
- attrlist=[u"distinguishedName", u"ms-Mcs-AdmPwd"])
-
- # Filter out non server hosts, search_s seems to return 3 extra entries
- # that are not computer classes, they do not have a distinguished name
- # set in the returned results
- valid_results = [attr for dn, attr in ldap_results if dn]
-
- if len(valid_results) == 0:
- raise AnsibleLookupError("Failed to find the server '%s' in the base '%s'" % (cn, search_base))
- elif len(valid_results) > 1:
- found_servers = [to_native(attr['distinguishedName'][0]) for attr in valid_results]
- raise AnsibleLookupError("Found too many results for the server '%s' in the base '%s'. Specify a more "
- "explicit search base for the server required. Found servers '%s'"
- % (cn, search_base, "', '".join(found_servers)))
-
- password = valid_results[0].get('ms-Mcs-AdmPwd', None)
- if not password:
- distinguished_name = to_native(valid_results[0]['distinguishedName'][0])
- raise AnsibleLookupError("The server '%s' did not have the LAPS attribute 'ms-Mcs-AdmPwd'" % distinguished_name)
-
- return to_native(password[0])
-
-
-class LookupModule(LookupBase):
-
- def run(self, terms, variables=None, **kwargs):
- if not HAS_LDAP:
- msg = missing_required_lib("python-ldap", url="https://pypi.org/project/python-ldap/")
- msg += ". Import Error: %s" % LDAP_IMP_ERR
- raise AnsibleLookupError(msg)
-
- # Load the variables and direct args into the lookup options
- self.set_options(var_options=variables, direct=kwargs)
- domain = self.get_option('domain')
- port = self.get_option('port')
- scheme = self.get_option('scheme')
- start_tls = self.get_option('start_tls')
- validate_certs = self.get_option('validate_certs')
- cacert_file = self.get_option('ca_cert')
- search_base = self.get_option('search_base')
- username = self.get_option('username')
- password = self.get_option('password')
- auth = self.get_option('auth')
- allow_plaintext = self.get_option('allow_plaintext')
-
- # Validate and set input values
- # https://www.openldap.org/lists/openldap-software/200202/msg00456.html
- validate_certs_map = {
- 'never': ldap.OPT_X_TLS_NEVER,
- 'allow': ldap.OPT_X_TLS_ALLOW,
- 'try': ldap.OPT_X_TLS_TRY,
- 'demand': ldap.OPT_X_TLS_DEMAND, # Same as OPT_X_TLS_HARD
- }
- validate_certs_value = validate_certs_map.get(validate_certs, None)
- if validate_certs_value is None:
- valid_keys = list(validate_certs_map.keys())
- valid_keys.sort()
- raise AnsibleLookupError("Invalid validate_certs value '%s': valid values are '%s'"
- % (validate_certs, "', '".join(valid_keys)))
-
- if auth not in ['gssapi', 'simple']:
- raise AnsibleLookupError("Invalid auth value '%s': expecting either 'gssapi', or 'simple'" % auth)
- elif auth == 'gssapi':
- if not ldap.SASL_AVAIL:
- raise AnsibleLookupError("Cannot use auth=gssapi when SASL is not configured with the local LDAP "
- "install")
- if username or password:
- raise AnsibleLookupError("Explicit credentials are not supported when auth='gssapi'. Call kinit "
- "outside of Ansible")
- elif auth == 'simple' and not (username and password):
- raise AnsibleLookupError("The username and password values are required when auth=simple")
-
- if ldapurl.isLDAPUrl(domain):
- ldap_url = ldapurl.LDAPUrl(ldapUrl=domain)
- else:
- port = port if port else 389 if scheme == 'ldap' else 636
- ldap_url = ldapurl.LDAPUrl(hostport="%s:%d" % (domain, port), urlscheme=scheme)
-
- # We have encryption if using LDAPS, or StartTLS is used, or we auth with SASL/GSSAPI
- encrypted = ldap_url.urlscheme == 'ldaps' or start_tls or auth == 'gssapi'
- if not encrypted and not allow_plaintext:
- raise AnsibleLookupError("Current configuration will result in plaintext traffic exposing credentials. "
- "Set auth=gssapi, scheme=ldaps, start_tls=True, or allow_plaintext=True to "
- "continue")
-
- if ldap_url.urlscheme == 'ldaps' or start_tls:
- # We cannot use conn.set_option as OPT_X_TLS_NEWCTX (required to use the new context) is not supported on
- # older distros like EL7. Setting it on the ldap object works instead
- if not ldap.TLS_AVAIL:
- raise AnsibleLookupError("Cannot use TLS as the local LDAP installed has not been configured to support it")
-
- ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, validate_certs_value)
- if cacert_file:
- cacert_path = os.path.expanduser(os.path.expandvars(cacert_file))
- if not os.path.exists(to_bytes(cacert_path)):
- raise AnsibleLookupError("The cacert_file specified '%s' does not exist" % to_native(cacert_path))
-
- try:
- # While this is a path, python-ldap expects a str/unicode and not bytes
- ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, to_text(cacert_path))
- except ValueError:
- # https://keathmilligan.net/python-ldap-and-macos/
- raise AnsibleLookupError("Failed to set path to cacert file, this is a known issue with older "
- "OpenLDAP libraries on the host. Update OpenLDAP and reinstall "
- "python-ldap to continue")
-
- conn_url = ldap_url.initializeUrl()
- conn = ldap.initialize(conn_url, bytes_mode=False)
- conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
- conn.set_option(ldap.OPT_REFERRALS, 0) # Allow us to search from the base
-
- # Make sure we run StartTLS before doing the bind to protect the credentials
- if start_tls:
- try:
- conn.start_tls_s()
- except ldap.LDAPError as err:
- raise AnsibleLookupError("Failed to send StartTLS to LDAP host '%s': %s"
- % (conn_url, to_native(err)))
-
- if auth == 'simple':
- try:
- conn.bind_s(to_text(username), to_text(password))
- except ldap.LDAPError as err:
- raise AnsibleLookupError("Failed to simple bind against LDAP host '%s': %s"
- % (conn_url, to_native(err)))
- else:
- try:
- conn.sasl_gssapi_bind_s()
- except ldap.AUTH_UNKNOWN as err:
- # The SASL GSSAPI binding is not installed, e.g. cyrus-sasl-gssapi. Give a better error message than
- # what python-ldap provides
- raise AnsibleLookupError("Failed to do a sasl bind against LDAP host '%s', the GSSAPI mech is not "
- "installed: %s" % (conn_url, to_native(err)))
- except ldap.LDAPError as err:
- raise AnsibleLookupError("Failed to do a sasl bind against LDAP host '%s': %s"
- % (conn_url, to_native(err)))
-
- try:
- if not search_base:
- root_dse = conn.read_rootdse_s()
- search_base = root_dse['defaultNamingContext'][0]
-
- ret = []
- # TODO: change method to search for all servers in 1 request instead of multiple requests
- for server in terms:
- ret.append(get_laps_password(conn, server, search_base))
- finally:
- conn.unbind_s()
-
- return ret