From 3b0807ad7b283c46c21862eb826dcbb4ad04e5e2 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 18 Apr 2024 07:52:27 +0200 Subject: Merging upstream version 9.4.0+dfsg. Signed-off-by: Daniel Baumann --- .../.github/workflows/ansible-test-windows.yml | 90 +- .../sqlserver/.github/workflows/ansible-test.yml | 84 +- .../sqlserver/.github/workflows/release.yml | 8 +- ansible_collections/lowlydba/sqlserver/ADOPTERS.md | 7 + .../lowlydba/sqlserver/CHANGELOG.rst | 106 + ansible_collections/lowlydba/sqlserver/FILES.json | 2231 ++++++++++---------- .../lowlydba/sqlserver/MANIFEST.json | 4 +- ansible_collections/lowlydba/sqlserver/README.md | 17 +- .../lowlydba/sqlserver/changelogs/changelog.yaml | 89 + .../lowlydba/sqlserver/meta/runtime.yml | 2 +- .../sqlserver/plugins/modules/ag_listener.ps1 | 4 +- .../sqlserver/plugins/modules/ag_replica.ps1 | 2 +- .../sqlserver/plugins/modules/agent_job.ps1 | 2 +- .../plugins/modules/agent_job_category.ps1 | 2 +- .../plugins/modules/agent_job_schedule.ps1 | 10 +- .../plugins/modules/agent_job_schedule.py | 9 +- .../sqlserver/plugins/modules/agent_job_step.ps1 | 2 +- .../plugins/modules/availability_group.ps1 | 2 +- .../lowlydba/sqlserver/plugins/modules/backup.ps1 | 2 +- .../sqlserver/plugins/modules/credential.ps1 | 2 +- .../sqlserver/plugins/modules/database.ps1 | 20 +- .../lowlydba/sqlserver/plugins/modules/database.py | 7 + .../sqlserver/plugins/modules/dba_multitool.ps1 | 2 +- .../plugins/modules/first_responder_kit.ps1 | 2 +- .../lowlydba/sqlserver/plugins/modules/hadr.ps1 | 2 +- .../sqlserver/plugins/modules/install_script.ps1 | 6 +- .../sqlserver/plugins/modules/install_script.py | 3 +- .../sqlserver/plugins/modules/instance_info.ps1 | 2 +- .../lowlydba/sqlserver/plugins/modules/login.ps1 | 15 +- .../lowlydba/sqlserver/plugins/modules/login.py | 13 + .../plugins/modules/maintenance_solution.ps1 | 2 +- .../lowlydba/sqlserver/plugins/modules/memory.ps1 | 2 +- .../sqlserver/plugins/modules/nonquery.ps1 | 2 +- .../plugins/modules/resource_governor.ps1 | 2 +- .../lowlydba/sqlserver/plugins/modules/restore.ps1 | 2 +- .../sqlserver/plugins/modules/rg_resource_pool.ps1 | 2 +- .../plugins/modules/rg_workload_group.ps1 | 2 +- .../lowlydba/sqlserver/plugins/modules/sa.ps1 | 2 +- .../lowlydba/sqlserver/plugins/modules/sa.py | 2 +- .../sqlserver/plugins/modules/sp_configure.ps1 | 2 +- .../sqlserver/plugins/modules/sp_whoisactive.ps1 | 2 +- .../lowlydba/sqlserver/plugins/modules/spn.ps1 | 4 +- .../sqlserver/plugins/modules/tcp_port.ps1 | 2 +- .../sqlserver/plugins/modules/traceflag.ps1 | 2 +- .../lowlydba/sqlserver/plugins/modules/user.ps1 | 3 +- .../targets/agent_job_schedule/tasks/main.yml | 6 +- .../tests/integration/targets/login/tasks/main.yml | 13 + .../targets/setup_sqlserver/tasks/main.yml | 3 +- .../targets/setup_sqlserver/vars/main.yml | 9 +- .../connection_plugins/local_pwsh.py | 1 - .../module_utils/Ansible.Basic.cs | 1481 ------------- .../module_utils/Ansible.ModuleUtils.AddType.psm1 | 397 ---- .../module_utils/_Ansible.Basic.cs | 1489 +++++++++++++ .../module_utils/_Ansible.ModuleUtils.AddType.psm1 | 397 ++++ .../shell_plugins/pwsh.py | 44 +- .../targets/setup_win_sqlserver/tasks/main.yml | 3 +- .../targets/win_ag_replica/tasks/main.yml | 5 +- 57 files changed, 3458 insertions(+), 3170 deletions(-) create mode 100644 ansible_collections/lowlydba/sqlserver/ADOPTERS.md delete mode 100644 ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.Basic.cs delete mode 100644 ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.ModuleUtils.AddType.psm1 create mode 100644 ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.Basic.cs create mode 100644 ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.ModuleUtils.AddType.psm1 (limited to 'ansible_collections/lowlydba') diff --git a/ansible_collections/lowlydba/sqlserver/.github/workflows/ansible-test-windows.yml b/ansible_collections/lowlydba/sqlserver/.github/workflows/ansible-test-windows.yml index a30426d3d..d764d6014 100644 --- a/ansible_collections/lowlydba/sqlserver/.github/workflows/ansible-test-windows.yml +++ b/ansible_collections/lowlydba/sqlserver/.github/workflows/ansible-test-windows.yml @@ -1,8 +1,6 @@ name: CI (Windows) on: - # Manual triggers workflow_dispatch: - # Run CI against all pushes (direct commits, also merged PRs), Pull Requests push: branches: - main @@ -22,7 +20,7 @@ on: # Run CI once per day (at 06:00 UTC) # This ensures that even if there haven't been commits that we are still testing against latest version of ansible-test for each ansible-base version schedule: - - cron: "0 6 * * *" + - cron: "0 8 * * *" # Cancel existing runs on new commits to a branch concurrency: @@ -32,7 +30,7 @@ concurrency: env: NAMESPACE: lowlydba COLLECTION_NAME: sqlserver - DBATOOLS_VERSION: "1.1.112" + DBATOOLS_VERSION: "2.0.0" jobs: ### @@ -42,30 +40,41 @@ jobs: integration: runs-on: ${{ matrix.os }} - name: I (Ⓐ${{ matrix.ansible }}+${{ matrix.os }}|grp${{ matrix.group }}) + name: I (Ⓐ${{ matrix.ansible }}+win-2022|grp${{ matrix.group }}) strategy: fail-fast: false matrix: os: - - windows-2019 + - windows-2022 ansible: - - stable-2.11 - - stable-2.12 - stable-2.13 - stable-2.14 + - stable-2.15 + - stable-2.16 - devel + python: + - python3 + - python3.10 group: # windows/group/#/ - "1" - "2" #- '3' - + exclude: + - ansible: stable-2.13 + python: python3.10 + - ansible: stable-2.14 + python: python3.10 + - ansible: stable-2.15 + python: python3.10 + - ansible: devel + python: python3 defaults: run: shell: wsl-bash {0} steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} @@ -78,7 +87,7 @@ jobs: - name: Set up the runner for PowerShell remoting shell: powershell run: | - $sb = [ScriptBlock]::Create((New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1')) + $sb = [ScriptBlock]::Create((New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/ansible/ansible/38e50c9f819a045ea4d40068f83e78adbfaf2e68/examples/scripts/ConfigureRemotingForAnsible.ps1')) & $sb -Verbose -ForceNewSSLCert 4>&1 - name: Enable winrm @@ -91,40 +100,18 @@ jobs: run: | Get-Service -Name MongoDB | Where-Object Status -eq 'Running' | Stop-Service -Force - - name: Install a SQL Server - continue-on-error: true - id: mssqlsuite - uses: potatoqualitee/mssqlsuite@v1.7 - with: - install: sqlengine - sa-password: L0wlydb4 - version: 2022 - - - name: Retry SQL Server install - id: retry1 - if: steps.mssqlsuite.outcome == 'failure' - uses: potatoqualitee/mssqlsuite@v1.7 - with: - install: sqlengine - sa-password: L0wlydb4 - version: 2022 - - name: Add a hosts entry shell: cmd run: echo 127.0.0.1 sqlserver >> "%WinDir%\System32\Drivers\etc\hosts" - - name: Install and cache PowerShell modules - uses: potatoqualitee/psmodulecache@v5.2 + - uses: Vampire/setup-wsl@v3.0.0 with: - modules-to-cache: dbatools - shell: powershell - - - uses: Vampire/setup-wsl@v1.3.4 - with: - distribution: Debian + distribution: Ubuntu-22.04 + update: "true" + use-cache: "true" additional-packages: | git - python3 + ${{ matrix.python }} python3-pip openssh-client @@ -156,8 +143,8 @@ jobs: - name: Install ansible-base (${{ matrix.ansible }}) run: | - python3 -m pip install --upgrade pip setuptools pypsrp --disable-pip-version-check --retries 10 - python3 -m pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check --retries 10 + ${{ matrix.python }} -m pip install --upgrade pip setuptools pypsrp --disable-pip-version-check --retries 10 + ${{ matrix.python }} -m pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check --retries 10 - name: Install collection dependencies id: collection-dependency @@ -169,25 +156,40 @@ jobs: run: ansible-galaxy collection install ansible.windows -p "${{ env.GHWS }}" - name: Set integration test options - shell: bash working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/tests/integration run: | cp integration_config.sample.yml integration_config.yml cp inventory.winrm.ci inventory.winrm - # Run the integration tests + - name: Install SQL Server + continue-on-error: true + id: mssqlsuite + uses: potatoqualitee/mssqlsuite@v1.7 + with: + install: sqlengine + sa-password: L0wlydb4 + version: 2022 + + - name: Retry SQL Server install + id: retry1 + if: steps.mssqlsuite.outcome == 'failure' + uses: potatoqualitee/mssqlsuite@v1.7 + with: + install: sqlengine + sa-password: L0wlydb4 + version: 2022 + - name: Run integration test run: | pushd "${{ env.GHWS }}/ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}" ansible-test windows-integration -v --color --retry-on-error --continue-on-error --diff --coverage --requirements windows/group/${{ matrix.group }}/ - # ansible-test support producing code coverage data - name: Generate coverage report run: | pushd "${{ env.GHWS }}/ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}" ansible-test coverage xml -v --requirements # See the reports at https://codecov.io/gh/lowlydba/lowlydba.sqlserver - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4.1.0 with: fail_ci_if_error: false diff --git a/ansible_collections/lowlydba/sqlserver/.github/workflows/ansible-test.yml b/ansible_collections/lowlydba/sqlserver/.github/workflows/ansible-test.yml index 01f271845..242c7a641 100644 --- a/ansible_collections/lowlydba/sqlserver/.github/workflows/ansible-test.yml +++ b/ansible_collections/lowlydba/sqlserver/.github/workflows/ansible-test.yml @@ -52,10 +52,10 @@ jobs: ansible: # It's important that Sanity is tested against all stable-X.Y branches # Testing against `devel` may fail as new tests are added. - - stable-2.11 - - stable-2.12 - stable-2.13 - stable-2.14 + - stable-2.15 + - stable-2.16 - devel runs-on: ubuntu-latest steps: @@ -63,35 +63,23 @@ jobs: # .../ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/ - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - - name: Set up Python - uses: actions/setup-python@v4 + - name: Run confidence tests + uses: ansible-community/ansible-test-gh-action@v1.14.1 with: - # it is just required to run that once as "ansible-test sanity" in the docker image - # will run on all python versions it supports. - python-version: 3.9 - - # Install the head of the given branch (devel, stable-2.10) - - name: Install ansible-base (${{ matrix.ansible }}) - run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check --retries 10 - - # run ansible-test sanity inside of Docker. - # The docker container has all the pinned dependencies that are required - # and all python versions ansible supports. - - name: Run sanity tests - run: ansible-test sanity --docker -v --color --coverage - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + ansible-core-version: ${{ matrix.ansible }} + testing-type: sanity + pull-request-change-detection: false - # ansible-test support producing code coverage date - name: Generate coverage report run: ansible-test coverage xml -v --requirements --group-by command --group-by version working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} # See the reports at https://codecov.io/gh/lowlydba/lowlydba.sqlserver - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4.1.0 with: fail_ci_if_error: false @@ -119,47 +107,45 @@ jobs: fail-fast: false matrix: ansible: - - stable-2.11 - - stable-2.12 - stable-2.13 - stable-2.14 + - stable-2.15 + - stable-2.16 - devel python: - - 3.9 + - 3.10 steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} - - name: Set up Python - uses: actions/setup-python@v4 - with: - # it is just required to run that once as "ansible-test integration" in the docker image - # will run on all python versions it supports. - python-version: 3.9 - - - name: Install ansible-base (${{ matrix.ansible }}) - run: pip install https://github.com/ansible/ansible/archive/${{ matrix.ansible }}.tar.gz --disable-pip-version-check --retries 10 - - - name: Install collection dependencies - id: collection-dependency - run: ansible-galaxy collection install community.general -p . - continue-on-error: true - - - name: Retry install collection dependencies - if: steps.collection-dependency.outcome == 'failure' - run: ansible-galaxy collection install community.general -p . - - name: Set integration test options working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}}/tests/integration run: cp integration_config.sample.yml integration_config.yml - # Run the integration tests - - name: Run integration test - run: ansible-test integration -v --color --retry-on-error --continue-on-error --diff --python ${{ matrix.python }} --docker --docker-network="${{ job.services.sqlserver.network }}" --coverage - working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} + # Prevent dbatools v2+ issues with newer docker image for 2.13 + - name: Run integration tests - v2.13 workaround + if: ${{ matrix.ansible == 'stable-2.13' }} + uses: ansible-community/ansible-test-gh-action@v1.14.1 + with: + docker-image: 'quay.io/ansible/default-test-container:6.13.0' + ansible-core-version: ${{ matrix.ansible }} + target-python-version: 3.9 + testing-type: integration + test-deps: community.general + pull-request-change-detection: false + + - name: Run integration tests + if: ${{ matrix.ansible != 'stable-2.13'}} + uses: ansible-community/ansible-test-gh-action@v1.14.1 + with: + ansible-core-version: ${{ matrix.ansible }} + #target-python-version: ${{ matrix.python }} + testing-type: integration + test-deps: community.general + pull-request-change-detection: false # ansible-test support producing code coverage date - name: Generate coverage report @@ -167,6 +153,6 @@ jobs: working-directory: ./ansible_collections/${{env.NAMESPACE}}/${{env.COLLECTION_NAME}} # See the reports at https://codecov.io/gh/lowlydba/lowlydba.sqlserver - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4.1.0 with: fail_ci_if_error: false diff --git a/ansible_collections/lowlydba/sqlserver/.github/workflows/release.yml b/ansible_collections/lowlydba/sqlserver/.github/workflows/release.yml index f7a3a9dec..201875bc0 100644 --- a/ansible_collections/lowlydba/sqlserver/.github/workflows/release.yml +++ b/ansible_collections/lowlydba/sqlserver/.github/workflows/release.yml @@ -15,10 +15,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 @@ -26,7 +26,7 @@ jobs: run: pip install pyyaml - name: Publish to Galaxy - uses: artis3n/ansible_galaxy_collection@v2.8.2 + uses: artis3n/ansible_galaxy_collection@v2.10.1 with: api_key: ${{ secrets.GALAXY_API_KEY }} @@ -69,7 +69,7 @@ jobs: - name: Create Release id: create_release - uses: softprops/action-gh-release@v0.1.15 + uses: softprops/action-gh-release@v2.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/ansible_collections/lowlydba/sqlserver/ADOPTERS.md b/ansible_collections/lowlydba/sqlserver/ADOPTERS.md new file mode 100644 index 000000000..264775136 --- /dev/null +++ b/ansible_collections/lowlydba/sqlserver/ADOPTERS.md @@ -0,0 +1,7 @@ +# Adopters + + + + +This is a list of organizations that have spoken publicly about their adoption or +production users that have added themselves: diff --git a/ansible_collections/lowlydba/sqlserver/CHANGELOG.rst b/ansible_collections/lowlydba/sqlserver/CHANGELOG.rst index 0414e8b66..a9c7adc65 100644 --- a/ansible_collections/lowlydba/sqlserver/CHANGELOG.rst +++ b/ansible_collections/lowlydba/sqlserver/CHANGELOG.rst @@ -5,6 +5,112 @@ lowlydba.sqlserver Release Notes .. contents:: Topics +v2.3.2 +====== + +Release Summary +--------------- + +Small fix for documentation and upstream fix available in dbatools v2.1.9. + +Bugfixes +-------- + +- Update documentation for agent_job_schedule to reflect proper input formatting. (https://github.com/lowlydba/lowlydba.sqlserver/pull/229) + +v2.3.1 +====== + +Release Summary +--------------- + +Update the install script feature to accommodate the latest minor DbOps release (v0.9.x) + +Minor Changes +------------- + +- Add new input strings to be compatible with dbops v0.9.x (https://github.com/lowlydba/lowlydba.sqlserver/pull/231) + +v2.3.0 +====== + +Release Summary +--------------- + +New feature from @OsirisDBA for skipping login password resets! + +Minor Changes +------------- + +- Add ability to prevent changing login's password, even if password supplied. + +v2.2.3 +====== + +Release Summary +--------------- + +Minor bugfixes. + +Bugfixes +-------- + +- Add ActiveStartDate to the compare properties so this item is marked accurately as changed. +- Fixed the formatting of the SPN by updating the backslash to a forward-slash for the $spn var (lowlydba.sqlserver.spn) + +v2.2.1 +====== + +Release Summary +--------------- + +Bugfix for database module in the context of availability groups. + +Minor Changes +------------- + +- Fixes error handling for Remove-DbaDatabase when joined to AvailabilityGroup, exception was not being thrown so we have to parse Status + +v2.2.0 +====== + +Release Summary +--------------- + +Bug fix in the database module. + +Minor Changes +------------- + +- Added only_accessible as an optional parameter to the database module (https://github.com/lowlydba/lowlydba.sqlserver/pull/198) + +v2.1.0 +====== + +Release Summary +--------------- + +Add sid to login, thanks @OsirisDBA! + +Minor Changes +------------- + +- Add refresh workaround for agent schedule bug where properties returned are stale. (https://github.com/lowlydba/lowlydba.sqlserver/pull/185) +- Added SID as an optional parameter to the login module (https://github.com/lowlydba/lowlydba.sqlserver/pull/189) + +v2.0.0 +====== + +Release Summary +--------------- + +A major version bump of DBATools to version 2+. This will guarantee compatibility with PowerShell Core versions 7.3+ and future SQL Server versions. For more information on that release, see https://blog.netnerds.net/2023/03/whats-new-dbatools-2.0/. Outside of major problems, new changes to this collection will not be backported to v1. + +Breaking Changes / Porting Guide +-------------------------------- + +- Updating minimum DBATools version to v2.0.0 to allow for pwsh 7.3+ compatibility. There may also be breaking change behavior in DBATools, see https://blog.netnerds.net/2023/03/whats-new-dbatools-2.0/. (https://github.com/lowlydba/lowlydba.sqlserver/pull/181) + v1.3.1 ====== diff --git a/ansible_collections/lowlydba/sqlserver/FILES.json b/ansible_collections/lowlydba/sqlserver/FILES.json index 3e5785a29..35b6495cd 100644 --- a/ansible_collections/lowlydba/sqlserver/FILES.json +++ b/ansible_collections/lowlydba/sqlserver/FILES.json @@ -8,1466 +8,1361 @@ "format": 1 }, { - "name": "CODE_OF_CONDUCT.md", + "name": "CHANGELOG.rst", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "14ec928234a7ed52bf8b458d31e4862335111e477e4dbe7fb543686c24115140", + "chksum_sha256": "aacf6b751586ed3ad211a33884e4382cbaed1ceeb5e17017e7a2e0a0d90dedd0", "format": 1 }, { - "name": "README.md", + "name": "CONTRIBUTING.md", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1e5e70b4cf447560cafa47c84e33845abc035f87b349cfebf2395b25c6326094", + "chksum_sha256": "eec219dbc09446ed3e9938c8f66378621a0548b056426df33e3ea32e26bb4dc8", "format": 1 }, { - "name": ".github", + "name": "LICENSE", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986", + "format": 1 + }, + { + "name": ".vscode", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": ".github/in-solidarity.yml", + "name": ".vscode/settings.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "43f54d1f6c1496d0a02ce3144f73d479f2e37ea3d2bb9e54ba08763ddfd230a2", + "chksum_sha256": "129f69fd05d6feacc20ea9f2edf00332ce20639fa3c35f4f4b0a42dea2835bac", "format": 1 }, { - "name": ".github/codecov.yml", + "name": ".vscode/extensions.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a42ee6fd570c21e6f7828ebb71585d819fd3fa126b3d98c39ea79565ce1a0ed6", + "chksum_sha256": "f72b83e1aa1301adb18ce0fe71ce6613d3cfb148f881b3e39c55359d41d3277f", "format": 1 }, { - "name": ".github/FUNDING.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1a09efd96d758af083de6b9468b6508672806abb882fd9fc16a1a23a67ab3acc", + "name": "tests", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": ".github/workflows", + "name": "tests/integration", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": ".github/workflows/release.yml", + "name": "tests/integration/inventory.winrm.ci", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3f7766b4e0f1b09cf939d122647613880bf11bb9ee73181e3303069aab2f312d", + "chksum_sha256": "d1a9b5a526214d256d89f06ac3180e7d73b63b7cd199a536888405e21f8768de", "format": 1 }, { - "name": ".github/workflows/ansible-test-windows.yml", + "name": "tests/integration/inventory", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "027a1dc37e1aed9bbd57e58dc8248504cde6770b1b37fe6e2930e5a1c1d0ba79", + "chksum_sha256": "0a28c1f749c45ff439aeeb826635429412f65c284d7d52ca7ff51b9dde495551", "format": 1 }, { - "name": ".github/workflows/docs-push.yml", + "name": "tests/integration/integration_config.sample.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9529da03eea03a258ab7ec8613310e62ad06fdbadd293d575070797d716443e9", + "chksum_sha256": "25e1d1343d93da99f01452b27af5f1b290b938b228ff934b0e84e6acd36916ec", "format": 1 }, { - "name": ".github/workflows/docs-pr.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "84a88873a148150b9b42877fa1c42697c05f631e39e618160bd99bf0f3652abd", + "name": "tests/integration/targets", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": ".github/workflows/ansible-test.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "34e2829089c5883da3e53d7de97ae1b9d50ed573bf27c7d3f42dc232240cb68e", + "name": "tests/integration/targets/win_restore", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": ".github/ISSUE_TEMPLATE", + "name": "tests/integration/targets/win_restore/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": ".github/ISSUE_TEMPLATE/bug_report.md", + "name": "tests/integration/targets/win_restore/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8d3db528d29f10782cc5b08a68999c7144efbeaa6724817d6c72a69f4c745a31", + "chksum_sha256": "25cec2155a81c7e38f39a8124b49ae2daf98d279ca19a1d2fe4e2dc16d406c9c", "format": 1 }, { - "name": ".github/ISSUE_TEMPLATE/feature_request.md", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "cd5b39aee355194f532b686c62a783c0657d8f7810586a757775769b291461a2", + "name": "tests/integration/targets/win_restore/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": ".github/dependabot.yml", + "name": "tests/integration/targets/win_restore/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a35bab1dd3e838ca5730aae35e4b127a052f8e03d5ed5437549e95f8424e621c", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": ".github/PULL_REQUEST_TEMPLATE.md", + "name": "tests/integration/targets/win_restore/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4ea1170a9065ecc1b0effb0e52f06fe42ef9936e86dfddb21c43efdd1c929b7b", + "chksum_sha256": "b522894638086953bde369a5f6c194a90c32338fefab24021b399659246ee20b", "format": 1 }, { - "name": "plugins", + "name": "tests/integration/targets/sp_configure", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules", + "name": "tests/integration/targets/sp_configure/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/credential.py", + "name": "tests/integration/targets/sp_configure/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "16a49e24a042e89e609a22adc1316559025f60bf24fb456c0acda09e611b6ec5", + "chksum_sha256": "c17643d6398d807c079ed122d9afc3f7d121e4720ac460693e3a6dc1bf9eb355", "format": 1 }, { - "name": "plugins/modules/hadr.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b2017667c8e572a1582cb076b3d543f4d7eba1ed6d66a7c0249d48b4f793868a", + "name": "tests/integration/targets/sp_configure/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/database.ps1", + "name": "tests/integration/targets/sp_configure/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "db141212c91271253c7a5438712450894bf47420e50d1e4b916a6d92a6f17e2f", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "plugins/modules/agent_job_step.py", + "name": "tests/integration/targets/sp_configure/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "56da01e0ba38203752b396a705ef7b385109c803de9787456ab9446353ef88db", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "plugins/modules/maintenance_solution.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "8d1065f37fb4535a0357063b29d0fb65ce71c3dbd953afde1715d9763c8d636d", + "name": "tests/integration/targets/win_sa", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/sa.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "7ef173d3b99d5ff729f300b637a67adb882be4f7ce7b3d102ea65e64bfb11f4e", + "name": "tests/integration/targets/win_sa/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/database.py", + "name": "tests/integration/targets/win_sa/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f91b64cc108c1b7b9926a80fb3d5e689493374b77bfd2228dd06beecbfaa2d0a", + "chksum_sha256": "f8a1f159fe12e4baf75982b00a0fff57296bd8b19e469913458531f0af2307d1", "format": 1 }, { - "name": "plugins/modules/restore.ps1", + "name": "tests/integration/targets/win_sa/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c7c556408d4a1778418b6e6b9497939f2760945ddbd8a5744e7f51bb7501fe1f", + "chksum_sha256": "3e5a273fb8fb0ecaa330c5beed437ab0d77fc765042c1baa4b97034f3d63de58", "format": 1 }, { - "name": "plugins/modules/instance_info.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "2c1f528f928cb542f56ba5e9f2126288ecff3447ab7cb5ee50bc8cf0db7db000", + "name": "tests/integration/targets/win_agent_job_category", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/rg_workload_group.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "90cae13aa924431ceddce76eb94f49576b4e8396227a141a2d81c9fbf5f9dd34", + "name": "tests/integration/targets/win_agent_job_category/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/nonquery.py", + "name": "tests/integration/targets/win_agent_job_category/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "28566664f6a3f97f72301bc34fa22af1421ead1ca572d651f241e960acc2be29", + "chksum_sha256": "637bd5e4ab78efba6ef44acb927e9d2188743d9d62d8ef4577ba8ca596dbd7f6", "format": 1 }, { - "name": "plugins/modules/spn.ps1", + "name": "tests/integration/targets/win_agent_job_category/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c349deb205aeb61078930059b3e8070878cda41fb6a40f866482aebfaaa358a3", + "chksum_sha256": "b4a1e70429ec84b35ba19e1696b30a39c4baeed6712c12ad93fd7ff62c42649a", "format": 1 }, { - "name": "plugins/modules/resource_governor.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a746d1d510e43d66429bc9c1654a6eb1d9c4e431ad451f182e649ed65fe6f36e", + "name": "tests/integration/targets/traceflag", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/ag_listener.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c91b831040e354aff0581367dcd1778b898ca424a92abf35786e9835e96c1018", + "name": "tests/integration/targets/traceflag/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/tcp_port.py", + "name": "tests/integration/targets/traceflag/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fcb5a1326cf73886733d6772f7623bd7e792563155c8d72a0d59312998215d91", + "chksum_sha256": "50cc511e187bab0f47387422459e654018bb6d5b8c408c49fe074cc92466560d", "format": 1 }, { - "name": "plugins/modules/rg_workload_group.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "62b1fd265aecaa6522bd5aaa6d008a33e98d102ee8fba6419043c4374e139b45", + "name": "tests/integration/targets/traceflag/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/user.ps1", + "name": "tests/integration/targets/traceflag/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "33898d0fe3dcf8e85edb9d8dd2fc144a4ebc4ea74b8b54879be48926396bc6f8", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "plugins/modules/traceflag.ps1", + "name": "tests/integration/targets/traceflag/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aa278d5f9bce404c957a7ff22d18de6f7be083f5f8c32b01c728fa792e6d21f3", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "plugins/modules/agent_job_schedule.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "6d16d9e00eabe5bcc8891e312517df43faa12dc235f9f0c025ae763742a4f371", + "name": "tests/integration/targets/dba_multitool", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/agent_job_schedule.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "4d8d54b56b4791914d18e982a72bb09231ba85ec59fb7b2772154c6f34dd0762", + "name": "tests/integration/targets/dba_multitool/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/restore.py", + "name": "tests/integration/targets/dba_multitool/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0f357dea6f735aae072bfee1d35335140a2a4cf3ac617ee68347cde8f7991bad", + "chksum_sha256": "9c2dc342256920c670d472b94856269834490da88bd511ce501d7158dd080ecd", "format": 1 }, { - "name": "plugins/modules/availability_group.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "8b3b47b92e9a558181210ab01de6d6637d3b39d61d647630926ac424a08303ef", + "name": "tests/integration/targets/dba_multitool/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/rg_resource_pool.py", + "name": "tests/integration/targets/dba_multitool/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a18afaa50ed7d7183a0a9458b8b4a62130d92670f5d68197c8272c498eef876e", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "plugins/modules/backup.ps1", + "name": "tests/integration/targets/dba_multitool/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e7cdc4254a27de68509a53758db8603bb86fe9495f119c3eea3d8431a74b1f33", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "plugins/modules/sp_whoisactive.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "26025dd39dc4bea36f72bcb0dd4a279245adde8e6be4792cc40ef90d02ade8e7", + "name": "tests/integration/targets/win_tcp_port", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/first_responder_kit.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "bf16bc535cfa590e884e99e3c406c602aca4c1322b9a9c86679d1980f18e5e1a", + "name": "tests/integration/targets/win_tcp_port/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/install_script.py", + "name": "tests/integration/targets/win_tcp_port/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e4c06e4e8a0d59008b39a64f468bcc9daa39db69c38b906826b8ae68239ef9c1", + "chksum_sha256": "d692ce8436946b398e6cb3ff85f4c0e6a500468fb623d144566b25db71a60af5", "format": 1 }, { - "name": "plugins/modules/login.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "094d8b444a09f7b5ae0d43f4ab60f1b5ab726f34a872a8353865e99297807103", + "name": "tests/integration/targets/win_tcp_port/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/sa.ps1", + "name": "tests/integration/targets/win_tcp_port/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e5344b122f26723049886b935d7ec19054845b6fbbdef75225138f318e02844a", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "plugins/modules/traceflag.py", + "name": "tests/integration/targets/win_tcp_port/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d08e57033e0da3f63f1c024446f02abdff41400dd0607a400f234468e05260ff", + "chksum_sha256": "823c89dbff7ce470f0ab6e7e3c41e7fa02b7b38fd4a1d5bcda2ecbcb98a4dbd7", "format": 1 }, { - "name": "plugins/modules/memory.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1c3e840a66bb01f5b809b7c9347594cfed73286cb589ca710eb3802f990fe9c8", + "name": "tests/integration/targets/agent_job", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/dba_multitool.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b5d35e4d415e3c5f097bafa3e89fafc330800278421bb80b78a28ff0be31fe8d", - "format": 1 - }, - { - "name": "plugins/modules/tcp_port.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "819aa2ed914e8989245c83f4af6e6794671e6bede649d71a1d1b68eb67dd57b3", + "name": "tests/integration/targets/agent_job/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/memory.ps1", + "name": "tests/integration/targets/agent_job/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "32ef5d4c7b5195fe126c307bd3fde03dc55b0e09e02bd58db6578c06137dc07f", + "chksum_sha256": "31c7e5478ab71d9b16cad90042519bd6cef26068f73dab84bf1b12fe6c6b1dcf", "format": 1 }, { - "name": "plugins/modules/maintenance_solution.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "126a8b7ea648ab2bc6e36db65a9b5ca85ca1c2224ad21445c176ea700b5a00ad", + "name": "tests/integration/targets/agent_job/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/backup.py", + "name": "tests/integration/targets/agent_job/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ddffc896a151a1c0a9d1798d1f7796d49aae2886f5aeb9c07ca72378d257a298", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "plugins/modules/agent_job_category.py", + "name": "tests/integration/targets/agent_job/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eda9101228bdf9db6dfce794c3d7cb51b2913f43cbfd6d2045179a74dad4f52e", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "plugins/modules/instance_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c6d60a465bcc5ab23e0ab7688479f2c54ca80c4d15f9a7a6adc0211f8aabd4fd", + "name": "tests/integration/targets/win_first_responder_kit", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/resource_governor.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "27d1f38306c23bfea82dc745425cf6cef0099156054bee4a497d0687866ade97", + "name": "tests/integration/targets/win_first_responder_kit/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/sp_configure.ps1", + "name": "tests/integration/targets/win_first_responder_kit/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6b1274247552e09c32acc4442f542a66a5805c90c472ded207da0cd8922e7482", + "chksum_sha256": "880bb341d99af44927b4791c9df077901daca5219411d812b36303e6b7c6d95c", "format": 1 }, { - "name": "plugins/modules/first_responder_kit.ps1", + "name": "tests/integration/targets/win_first_responder_kit/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e4c552d6cb6dc6da95881c82267085c3cc9bd54b76cd5022bc3b0bcd1c370e8d", + "chksum_sha256": "eb9346a60cae33ea572746b34b03e115c6d4f06b6c1f39bf1fa4eb12ee42e6bb", "format": 1 }, { - "name": "plugins/modules/agent_job_step.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "7804759c5225d445865cf4a915de70588026ca64a336bd364e1f2b41a6d317cc", + "name": "tests/integration/targets/win_maintenance_solution", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/sp_configure.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "2715043d68e455a59bd7ff7028c769c23d662ae04b937128aec461a39c544bf5", + "name": "tests/integration/targets/win_maintenance_solution/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/ag_listener.ps1", + "name": "tests/integration/targets/win_maintenance_solution/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b05053dcf1f266a21de546507eeb02bf780854de655bfed76eeaa2240dc2b803", + "chksum_sha256": "51ae5e4c8a06b47364e63ec20fc30138f7d30ef5c0fda58701a248cdaad0481c", "format": 1 }, { - "name": "plugins/modules/hadr.ps1", + "name": "tests/integration/targets/win_maintenance_solution/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be5c12d9c83d950c86a0a2e0b0dca9d4d99a4f4540039b84e64a0bc70d7393a3", + "chksum_sha256": "7d262d00ae91b2b827898ae863725e5579f68d3390fb255cc591560b4f616367", "format": 1 }, { - "name": "plugins/modules/agent_job_category.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "815dc61c98e04d7ff02bff2fd528d02512432323d8cd9c14394a6228e83a3cad", + "name": "tests/integration/targets/agent_job_category", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/dba_multitool.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "0236dc7ccb91ecf1e0fdb832a40a8f82ed90ad888d7e02f41b7a2848ddc48bef", + "name": "tests/integration/targets/agent_job_category/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/spn.py", + "name": "tests/integration/targets/agent_job_category/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "57a8e8f95263b83394aaf4342759ffccbfa20315cf8d208aecee5b54f46d7a72", + "chksum_sha256": "0544826a56fa9285258e41f18f989bad46a9a333c4508b6ff52991cb820ef6dd", "format": 1 }, { - "name": "plugins/modules/install_script.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1298f7713c30765a05794c4dd8f533084869dd0752199994d6ce885d65b0599b", + "name": "tests/integration/targets/agent_job_category/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/ag_replica.ps1", + "name": "tests/integration/targets/agent_job_category/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e8b318c3531976bb59a78d7bff1581a827195458090ddd8777c6de87753392ef", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "plugins/modules/rg_resource_pool.ps1", + "name": "tests/integration/targets/agent_job_category/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "27b665f6956f9c403232ac75baf94ef429b9ac12c76f89b2160f6faf153ec941", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "plugins/modules/user.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "99b2b1074ac11298c64b987414934b55e1e95a482bcc3185285662482dbf55b7", + "name": "tests/integration/targets/sp_whoisactive", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/nonquery.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "63fbe59992098ce75e62d692b9b4d7cc00b6e2d564496f402f496e51118d28f3", + "name": "tests/integration/targets/sp_whoisactive/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/ag_replica.py", + "name": "tests/integration/targets/sp_whoisactive/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3d7f122d89145949eaeabf78c2e4747ba9158611d9dd28efe19a6c23b61a18cf", + "chksum_sha256": "6ea486055f1c09c041e9b353582799bb37ed536cb8e7e6bf89920a1d79cc361f", "format": 1 }, { - "name": "plugins/modules/sp_whoisactive.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "5e75ed0cd32bab885f0969ebc9d523a43ee24d2796a956e6a87bbf4a415ae911", + "name": "tests/integration/targets/sp_whoisactive/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/agent_job.ps1", + "name": "tests/integration/targets/sp_whoisactive/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "62efb5344bf2ff3d8201b87dc82ba9b42adb91657d8f44c03736229bf8f52313", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "plugins/modules/availability_group.ps1", + "name": "tests/integration/targets/sp_whoisactive/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a4f09ebba1bcbbecbfee5455ab196aa334020ab9bea0ff8a69d38851a774eddf", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "plugins/modules/credential.ps1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "19f45fc1ab63a730813bb70e29643ba18f8b43c070a1d15be6aa8867e38d7d26", + "name": "tests/integration/targets/user", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/agent_job.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "9476d4b38459e10be25b64c96bf7b2b9bb4f49045d15cd36f959737eec194d34", + "name": "tests/integration/targets/user/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/login.ps1", + "name": "tests/integration/targets/user/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "68c4da04ac19c9b00bd100271b98184df756eb01208f91d5e605c0657ad91760", + "chksum_sha256": "772de87469867e5ba4167ca395dd6a50004daeddff4cf8a6ca345cf97ca12077", "format": 1 }, { - "name": "plugins/doc_fragments", + "name": "tests/integration/targets/user/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "plugins/doc_fragments/sql_credentials.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "8319c0f26d235fb9dd33444fe7cfe963324207e64f77423098fb0a6c071be791", - "format": 1 - }, - { - "name": "plugins/doc_fragments/state.py", + "name": "tests/integration/targets/user/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ae0b5a340638525f1d65822b592ccba03c72dd937e8f1f60f41539f80a1af2f7", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "plugins/doc_fragments/attributes.py", + "name": "tests/integration/targets/user/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cdffff9cfa27f07533b806e63d11b9a752144eb5f2d7d8c8837e7a4efa4da4c7", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "plugins/module_utils", + "name": "tests/integration/targets/win_hadr", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "plugins/module_utils/_SqlServerUtils.psm1", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "4fdfc528ea4a54118f616738c9630066e47e0d010c2b60cbecd851a5b5547c3f", - "format": 1 - }, - { - "name": "docs", + "name": "tests/integration/targets/win_hadr/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "docs/.gitkeep", + "name": "tests/integration/targets/win_hadr/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b", + "chksum_sha256": "e5341d244291343a5efba167280a123556be0ce4480c8cab2282fc3e2c288609", "format": 1 }, { - "name": "changelogs", + "name": "tests/integration/targets/win_hadr/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "changelogs/config.yaml", + "name": "tests/integration/targets/win_hadr/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1e054fb68c58140c282fbaf0150eee1bf80ad925196dddd74e848e91b7315a1e", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "changelogs/changelog.yaml", + "name": "tests/integration/targets/win_hadr/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "84869c094d776ac71026856552afea3b0b5e31450222ecf2cf743081e019eeea", + "chksum_sha256": "823c89dbff7ce470f0ab6e7e3c41e7fa02b7b38fd4a1d5bcda2ecbcb98a4dbd7", "format": 1 }, { - "name": "changelogs/fragments", + "name": "tests/integration/targets/win_memory", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "changelogs/fragments/.keep", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "format": 1 - }, - { - "name": "MAINTAINERS", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "29b1b04e645e0c11e59c48cfe7bac3dbe16f787a9d6114847d9a5c3b5990e731", - "format": 1 - }, - { - "name": "CONTRIBUTING.md", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "eec219dbc09446ed3e9938c8f66378621a0548b056426df33e3ea32e26bb4dc8", - "format": 1 - }, - { - "name": "meta", + "name": "tests/integration/targets/win_memory/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "meta/runtime.yml", + "name": "tests/integration/targets/win_memory/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5be7885f2e0f072d87dedbab542a787597a3cd3cabab2826d902233af114edce", + "chksum_sha256": "c32e78042afc05d5738763ed9a9281f6e6a5e03231c2124087400143409ec6d6", "format": 1 }, { - "name": "LICENSE", + "name": "tests/integration/targets/win_memory/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986", + "chksum_sha256": "29e8c25ab424e16e434d902ced6f408da8a4f1f9363126caa03092f62bcb43aa", "format": 1 }, { - "name": "tests", + "name": "tests/integration/targets/win_instance_info", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration", + "name": "tests/integration/targets/win_instance_info/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/integration_config.sample.yml", + "name": "tests/integration/targets/win_instance_info/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "25e1d1343d93da99f01452b27af5f1b290b938b228ff934b0e84e6acd36916ec", + "chksum_sha256": "ce5de48e8e8a42b74d629f088dc4e10650fe45b811ef394b852884e11ac3d20b", "format": 1 }, { - "name": "tests/integration/.ansible-lint", + "name": "tests/integration/targets/win_instance_info/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "982c0b7fe8683e818a27cf59b6a6892d91c277703c81e2db35994f63ef90e7fc", + "chksum_sha256": "96874064bd5afc3782b688417ee53a256f2aeee2b3f7be9db26ef14760752d33", "format": 1 }, { - "name": "tests/integration/targets", + "name": "tests/integration/targets/win_availability_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_category", + "name": "tests/integration/targets/win_availability_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_category/aliases", + "name": "tests/integration/targets/win_availability_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b4a1e70429ec84b35ba19e1696b30a39c4baeed6712c12ad93fd7ff62c42649a", + "chksum_sha256": "8f66aa5fd04f4ae573bafb0e037877232be65d063c0569b6a7fa9020081507c3", "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_category/meta", + "name": "tests/integration/targets/win_availability_group/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_category/meta/main.yml", + "name": "tests/integration/targets/win_availability_group/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "637bd5e4ab78efba6ef44acb927e9d2188743d9d62d8ef4577ba8ca596dbd7f6", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/setup_win_sqlserver", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/setup_win_sqlserver/aliases", + "name": "tests/integration/targets/win_availability_group/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "105c5f0785da8d117d54b796fedefa4ddbd7ec65b52058539abe49f327d06db8", + "chksum_sha256": "b522894638086953bde369a5f6c194a90c32338fefab24021b399659246ee20b", "format": 1 }, { - "name": "tests/integration/targets/setup_win_sqlserver/tasks", + "name": "tests/integration/targets/rg_resource_pool", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_win_sqlserver/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "339b0338ba60e7a9f16ef083d385fd1df922c058bc10e044eda5f7f436a61ff5", - "format": 1 - }, - { - "name": "tests/integration/targets/setup_win_sqlserver/meta", + "name": "tests/integration/targets/rg_resource_pool/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_win_sqlserver/meta/main.yml", + "name": "tests/integration/targets/rg_resource_pool/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0717e3c911ac3a45ebb713a535b723d4ebc229a24910a45349c2e8f9ce88cae8", + "chksum_sha256": "669c18b75e00a7e66b58ecbb24511bc42825b97529a6e3ad085ef35ff944ffaa", "format": 1 }, { - "name": "tests/integration/targets/setup_win_sqlserver/vars", + "name": "tests/integration/targets/rg_resource_pool/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_win_sqlserver/vars/main.yml", + "name": "tests/integration/targets/rg_resource_pool/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f773fabf54dffb1da94c9a66e897675dd8831d87d1ff525edeaa581ac0963c7e", - "format": 1 - }, - { - "name": "tests/integration/targets/traceflag", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/traceflag/aliases", + "name": "tests/integration/targets/rg_resource_pool/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/traceflag/tasks", + "name": "tests/integration/targets/install_script", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/traceflag/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "50cc511e187bab0f47387422459e654018bb6d5b8c408c49fe074cc92466560d", - "format": 1 - }, - { - "name": "tests/integration/targets/traceflag/meta", + "name": "tests/integration/targets/install_script/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/traceflag/meta/main.yml", + "name": "tests/integration/targets/install_script/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "85e9885a3bb1a9621c0ac183c3c831efe453bbb5eddbb4d6351a620164b33672", "format": 1 }, { - "name": "tests/integration/targets/sp_configure", + "name": "tests/integration/targets/install_script/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/sp_configure/aliases", + "name": "tests/integration/targets/install_script/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", - "format": 1 - }, - { - "name": "tests/integration/targets/sp_configure/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/sp_configure/tasks/main.yml", + "name": "tests/integration/targets/install_script/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c17643d6398d807c079ed122d9afc3f7d121e4720ac460693e3a6dc1bf9eb355", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/sp_configure/meta", + "name": "tests/integration/targets/install_script/files", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/sp_configure/meta/main.yml", + "name": "tests/integration/targets/install_script/files/1-select-choice.sql", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "fde2acd9de812005948b5935c0c335889828e14ee58dbcc58a205096cdb2266f", "format": 1 }, { - "name": "tests/integration/targets/sp_whoisactive", + "name": "tests/integration/targets/instance_info", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/sp_whoisactive/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", - "format": 1 - }, - { - "name": "tests/integration/targets/sp_whoisactive/tasks", + "name": "tests/integration/targets/instance_info/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/sp_whoisactive/tasks/main.yml", + "name": "tests/integration/targets/instance_info/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6ea486055f1c09c041e9b353582799bb37ed536cb8e7e6bf89920a1d79cc361f", + "chksum_sha256": "22e5f3e538dfd862aebe6429f2d06293499bcd83a7b8da0f6afbee5f8033366b", "format": 1 }, { - "name": "tests/integration/targets/sp_whoisactive/meta", + "name": "tests/integration/targets/instance_info/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/sp_whoisactive/meta/main.yml", + "name": "tests/integration/targets/instance_info/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/win_spn", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/win_spn/aliases", + "name": "tests/integration/targets/instance_info/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b522894638086953bde369a5f6c194a90c32338fefab24021b399659246ee20b", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/win_spn/tasks", + "name": "tests/integration/targets/win_sp_configure", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_spn/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "25fe644417d284f14218215aed1e5e3ae8f920c32cdba3b349e8574f10c41f7c", - "format": 1 - }, - { - "name": "tests/integration/targets/win_spn/meta", + "name": "tests/integration/targets/win_sp_configure/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_spn/meta/main.yml", + "name": "tests/integration/targets/win_sp_configure/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", - "format": 1 - }, - { - "name": "tests/integration/targets/win_rg_workload_group", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "4c58bedc5bf4354f6a8e46bd6e292a388f347a5babcc36a61cebd68081a3d1c7", "format": 1 }, { - "name": "tests/integration/targets/win_rg_workload_group/aliases", + "name": "tests/integration/targets/win_sp_configure/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "30128d716d50ee4404c8f9a1e5f921f3a830a18171470a5de586eac0799cfe5c", + "chksum_sha256": "f9f102cc9b61991c72e62216c363357b58ba6ef812f7838b194d76b9a37ee6dd", "format": 1 }, { - "name": "tests/integration/targets/win_rg_workload_group/meta", + "name": "tests/integration/targets/win_nonquery", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_rg_workload_group/meta/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "ace519beeabaa6fff00bf4230f11205f2eb88ef957a29ff4991e717ab3cd8ed2", - "format": 1 - }, - { - "name": "tests/integration/targets/rg_workload_group", + "name": "tests/integration/targets/win_nonquery/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/rg_workload_group/aliases", + "name": "tests/integration/targets/win_nonquery/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", - "format": 1 - }, - { - "name": "tests/integration/targets/rg_workload_group/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "0dae571f5e423080bf9bdaac127360812ea64380e435c29f03142c56aadb4484", "format": 1 }, { - "name": "tests/integration/targets/rg_workload_group/tasks/main.yml", + "name": "tests/integration/targets/win_nonquery/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "20da00d72375b1ce6f9644d75d1c7d8066bd92e88c919abfd0e6813363a19b92", + "chksum_sha256": "eb1fa7982c88abde5d789d5b541bc8016f99025f732bef1cca7ba4ca457b6f7b", "format": 1 }, { - "name": "tests/integration/targets/rg_workload_group/meta", + "name": "tests/integration/targets/win_login", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/rg_workload_group/meta/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", - "format": 1 - }, - { - "name": "tests/integration/targets/win_first_responder_kit", + "name": "tests/integration/targets/win_login/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_first_responder_kit/aliases", + "name": "tests/integration/targets/win_login/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eb9346a60cae33ea572746b34b03e115c6d4f06b6c1f39bf1fa4eb12ee42e6bb", - "format": 1 - }, - { - "name": "tests/integration/targets/win_first_responder_kit/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "18dbd3b87064b3336556de28cdb4a48564c66a2ae9123c90cce8bdb1860e97d9", "format": 1 }, { - "name": "tests/integration/targets/win_first_responder_kit/meta/main.yml", + "name": "tests/integration/targets/win_login/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "880bb341d99af44927b4791c9df077901daca5219411d812b36303e6b7c6d95c", + "chksum_sha256": "71529f18c9a617354c7ae2d0942307ee460e46dcf304073e6b83f0d9e5e3261a", "format": 1 }, { - "name": "tests/integration/targets/win_credential", + "name": "tests/integration/targets/win_spn", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_credential/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "db8628e2c4d331f6b0a0263ae6c01220b719d3aa44e806849ba93acff90b3e53", - "format": 1 - }, - { - "name": "tests/integration/targets/win_credential/meta", + "name": "tests/integration/targets/win_spn/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_credential/meta/main.yml", + "name": "tests/integration/targets/win_spn/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c4531eb647b3263f0f9611fea8ff1c0b2ce30c06437ffe41963e146f94a023a4", + "chksum_sha256": "25fe644417d284f14218215aed1e5e3ae8f920c32cdba3b349e8574f10c41f7c", "format": 1 }, { - "name": "tests/integration/targets/win_rg_resource_pool", + "name": "tests/integration/targets/win_spn/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_rg_resource_pool/aliases", + "name": "tests/integration/targets/win_spn/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f514a090cace343c41b298fa180e6a993fc535cf9fd0498424e1db2f097261a4", - "format": 1 - }, - { - "name": "tests/integration/targets/win_rg_resource_pool/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/win_rg_resource_pool/meta/main.yml", + "name": "tests/integration/targets/win_spn/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cfce66e3f2dc81d8b04d033c770f490560112a14e8de1c28c7b93e93757dfda8", + "chksum_sha256": "b522894638086953bde369a5f6c194a90c32338fefab24021b399659246ee20b", "format": 1 }, { - "name": "tests/integration/targets/win_restore", + "name": "tests/integration/targets/resource_governor", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_restore/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b522894638086953bde369a5f6c194a90c32338fefab24021b399659246ee20b", - "format": 1 - }, - { - "name": "tests/integration/targets/win_restore/tasks", + "name": "tests/integration/targets/resource_governor/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_restore/tasks/main.yml", + "name": "tests/integration/targets/resource_governor/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "25cec2155a81c7e38f39a8124b49ae2daf98d279ca19a1d2fe4e2dc16d406c9c", + "chksum_sha256": "b0e5d378ac5c85985d61002fb7ac7f22f8f37326bb10d5fd09c3553beea37731", "format": 1 }, { - "name": "tests/integration/targets/win_restore/meta", + "name": "tests/integration/targets/resource_governor/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_restore/meta/main.yml", + "name": "tests/integration/targets/resource_governor/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/user", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/user/aliases", + "name": "tests/integration/targets/resource_governor/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/user/tasks", + "name": "tests/integration/targets/win_backup", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/user/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "772de87469867e5ba4167ca395dd6a50004daeddff4cf8a6ca345cf97ca12077", - "format": 1 - }, - { - "name": "tests/integration/targets/user/meta", + "name": "tests/integration/targets/win_backup/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/user/meta/main.yml", + "name": "tests/integration/targets/win_backup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "9e6816dbbf21d3dba22fc22b8da0f0cc4cef6ac1dd82aefaab45a38c0fe3ecee", "format": 1 }, { - "name": "tests/integration/targets/win_dba_multitool", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/win_dba_multitool/aliases", + "name": "tests/integration/targets/win_backup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "65187564e8be2b9da7c1a7bc5e86687aa032caca1a4b8517e9cfe2b50ebc1965", + "chksum_sha256": "f4894d7d372026d355a62fe57e4c54da2b6588eb2df68b2bcfb3d6620525da09", "format": 1 }, { - "name": "tests/integration/targets/win_dba_multitool/meta", + "name": "tests/integration/targets/maintenance_solution", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_dba_multitool/meta/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f119d90651290bfdbd959b50880d02d480f375e19cb06989384d3b018e3b95dc", - "format": 1 - }, - { - "name": "tests/integration/targets/win_nonquery", + "name": "tests/integration/targets/maintenance_solution/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_nonquery/aliases", + "name": "tests/integration/targets/maintenance_solution/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eb1fa7982c88abde5d789d5b541bc8016f99025f732bef1cca7ba4ca457b6f7b", + "chksum_sha256": "d6841548d89da6e201186a5bd9ba2f370aff1ed3818fc9d5609a26a7405bd088", "format": 1 }, { - "name": "tests/integration/targets/win_nonquery/meta", + "name": "tests/integration/targets/maintenance_solution/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_nonquery/meta/main.yml", + "name": "tests/integration/targets/maintenance_solution/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0dae571f5e423080bf9bdaac127360812ea64380e435c29f03142c56aadb4484", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/win_install_script", + "name": "tests/integration/targets/maintenance_solution/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "format": 1 + }, + { + "name": "tests/integration/targets/win_user", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_install_script/files", + "name": "tests/integration/targets/win_user/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_install_script/files/1-select-choice.sql", + "name": "tests/integration/targets/win_user/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fde2acd9de812005948b5935c0c335889828e14ee58dbcc58a205096cdb2266f", + "chksum_sha256": "805393b91b743ad8f62db1f7301c2c9c85cd78b64633986e456aa3add70d5419", "format": 1 }, { - "name": "tests/integration/targets/win_install_script/aliases", + "name": "tests/integration/targets/win_user/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "823c89dbff7ce470f0ab6e7e3c41e7fa02b7b38fd4a1d5bcda2ecbcb98a4dbd7", + "chksum_sha256": "4d4819a1314f1ea6a500be90e727a92fb9b964511644c7162c869e351037c2f2", "format": 1 }, { - "name": "tests/integration/targets/win_install_script/tasks", + "name": "tests/integration/targets/win_ag_replica", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_install_script/tasks/main.yml", + "name": "tests/integration/targets/win_ag_replica/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/win_ag_replica/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f6dc29e973e9e7c8c7396cda456a513614d795455331165968588cbfc622726e", + "chksum_sha256": "257be045f263df194afe43af6d42e581e5acce5c0bb2fbd11eecd8569d2c43d1", "format": 1 }, { - "name": "tests/integration/targets/win_install_script/meta", + "name": "tests/integration/targets/win_ag_replica/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_install_script/meta/main.yml", + "name": "tests/integration/targets/win_ag_replica/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/rg_resource_pool", + "name": "tests/integration/targets/win_ag_replica/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b522894638086953bde369a5f6c194a90c32338fefab24021b399659246ee20b", + "format": 1 + }, + { + "name": "tests/integration/targets/win_rg_workload_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/rg_resource_pool/aliases", + "name": "tests/integration/targets/win_rg_workload_group/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/win_rg_workload_group/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "chksum_sha256": "ace519beeabaa6fff00bf4230f11205f2eb88ef957a29ff4991e717ab3cd8ed2", "format": 1 }, { - "name": "tests/integration/targets/rg_resource_pool/tasks", + "name": "tests/integration/targets/win_rg_workload_group/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "30128d716d50ee4404c8f9a1e5f921f3a830a18171470a5de586eac0799cfe5c", + "format": 1 + }, + { + "name": "tests/integration/targets/database", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/rg_resource_pool/tasks/main.yml", + "name": "tests/integration/targets/database/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/database/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "669c18b75e00a7e66b58ecbb24511bc42825b97529a6e3ad085ef35ff944ffaa", + "chksum_sha256": "096c592c99e22c947444c3cefe3007bdc7b6370b7c814b0c6cc0e8bd1b6f77c5", "format": 1 }, { - "name": "tests/integration/targets/rg_resource_pool/meta", + "name": "tests/integration/targets/database/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/rg_resource_pool/meta/main.yml", + "name": "tests/integration/targets/database/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver", + "name": "tests/integration/targets/database/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "format": 1 + }, + { + "name": "tests/integration/targets/sa", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver/tasks", + "name": "tests/integration/targets/sa/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver/tasks/main.yml", + "name": "tests/integration/targets/sa/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b36f45734e2fa1f527c185e1e9bfff3695f8b0fdbed70713ecbd72aaedd5b2fd", + "chksum_sha256": "4ab5c5e605be645cc3e9b27e4c767366504d3191f99d9bb8aac1be6faea59e81", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver/vars", + "name": "tests/integration/targets/sa/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver/vars/main.yml", + "name": "tests/integration/targets/sa/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "25da9d954dd20e30473963a6a1eeb48664272bfa186c934ffc5bd9121dc0858f", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver/defaults", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/sa/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver/defaults/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "454653b07873ad71128411eba4df7f2b86352fd4b884e667e045cab2b83ff4aa", + "name": "tests/integration/targets/win_credential", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_login", + "name": "tests/integration/targets/win_credential/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_login/aliases", + "name": "tests/integration/targets/win_credential/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "71529f18c9a617354c7ae2d0942307ee460e46dcf304073e6b83f0d9e5e3261a", + "chksum_sha256": "c4531eb647b3263f0f9611fea8ff1c0b2ce30c06437ffe41963e146f94a023a4", "format": 1 }, { - "name": "tests/integration/targets/win_login/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/win_credential/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "db8628e2c4d331f6b0a0263ae6c01220b719d3aa44e806849ba93acff90b3e53", "format": 1 }, { - "name": "tests/integration/targets/win_login/meta/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "18dbd3b87064b3336556de28cdb4a48564c66a2ae9123c90cce8bdb1860e97d9", + "name": "tests/integration/targets/win_agent_job_step", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_sp_configure", + "name": "tests/integration/targets/win_agent_job_step/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_sp_configure/aliases", + "name": "tests/integration/targets/win_agent_job_step/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f9f102cc9b61991c72e62216c363357b58ba6ef812f7838b194d76b9a37ee6dd", + "chksum_sha256": "bd6596491fb29701a783f70e0cc7e04bcb54c3af0306ff39166d7ffd01e57143", "format": 1 }, { - "name": "tests/integration/targets/win_sp_configure/meta", + "name": "tests/integration/targets/win_agent_job_step/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "47352893485e47a64c32139b049f01c0aa68e79591c0595922e0acffa2665523", + "format": 1 + }, + { + "name": "tests/integration/targets/win_dba_multitool", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_sp_configure/meta/main.yml", + "name": "tests/integration/targets/win_dba_multitool/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/win_dba_multitool/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4c58bedc5bf4354f6a8e46bd6e292a388f347a5babcc36a61cebd68081a3d1c7", + "chksum_sha256": "f119d90651290bfdbd959b50880d02d480f375e19cb06989384d3b018e3b95dc", + "format": 1 + }, + { + "name": "tests/integration/targets/win_dba_multitool/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "65187564e8be2b9da7c1a7bc5e86687aa032caca1a4b8517e9cfe2b50ebc1965", "format": 1 }, { @@ -1477,13 +1372,6 @@ "chksum_sha256": null, "format": 1 }, - { - "name": "tests/integration/targets/win_sp_whoisactive/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "0e25bc398118036b0ab0185bdf43aeb2f586af8d25ba057222e7794aab2cf3b2", - "format": 1 - }, { "name": "tests/integration/targets/win_sp_whoisactive/meta", "ftype": "dir", @@ -1499,472 +1387,367 @@ "format": 1 }, { - "name": "tests/integration/targets/nonquery", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/win_sp_whoisactive/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0e25bc398118036b0ab0185bdf43aeb2f586af8d25ba057222e7794aab2cf3b2", "format": 1 }, { - "name": "tests/integration/targets/nonquery/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "name": "tests/integration/targets/credential", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/nonquery/tasks", + "name": "tests/integration/targets/credential/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/nonquery/tasks/main.yml", + "name": "tests/integration/targets/credential/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "851bf7899fb14d2c976f6d2b1df869b108ab5f4440e2c57af920e06f7c59f07f", + "chksum_sha256": "502c966d269ba16b8f50711aa3413b89361ca26241b95ea42bfadbb543078190", "format": 1 }, { - "name": "tests/integration/targets/nonquery/meta", + "name": "tests/integration/targets/credential/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/nonquery/meta/main.yml", + "name": "tests/integration/targets/credential/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/resource_governor", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/resource_governor/aliases", + "name": "tests/integration/targets/credential/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/resource_governor/tasks", + "name": "tests/integration/targets/rg_workload_group", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/resource_governor/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b0e5d378ac5c85985d61002fb7ac7f22f8f37326bb10d5fd09c3553beea37731", - "format": 1 - }, - { - "name": "tests/integration/targets/resource_governor/meta", + "name": "tests/integration/targets/rg_workload_group/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/resource_governor/meta/main.yml", + "name": "tests/integration/targets/rg_workload_group/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", - "format": 1 - }, - { - "name": "tests/integration/targets/memory", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/memory/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "chksum_sha256": "20da00d72375b1ce6f9644d75d1c7d8066bd92e88c919abfd0e6813363a19b92", "format": 1 }, { - "name": "tests/integration/targets/memory/tasks", + "name": "tests/integration/targets/rg_workload_group/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/memory/tasks/main.yml", + "name": "tests/integration/targets/rg_workload_group/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "571c3ec667aa8c42235cf6a6d91e9ce5bcc8785653474f6a1d7bdd6166256705", - "format": 1 - }, - { - "name": "tests/integration/targets/memory/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/memory/meta/main.yml", + "name": "tests/integration/targets/rg_workload_group/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/win_sa", + "name": "tests/integration/targets/win_rg_resource_pool", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_sa/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3e5a273fb8fb0ecaa330c5beed437ab0d77fc765042c1baa4b97034f3d63de58", - "format": 1 - }, - { - "name": "tests/integration/targets/win_sa/meta", + "name": "tests/integration/targets/win_rg_resource_pool/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_sa/meta/main.yml", + "name": "tests/integration/targets/win_rg_resource_pool/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f8a1f159fe12e4baf75982b00a0fff57296bd8b19e469913458531f0af2307d1", - "format": 1 - }, - { - "name": "tests/integration/targets/win_agent_job", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "cfce66e3f2dc81d8b04d033c770f490560112a14e8de1c28c7b93e93757dfda8", "format": 1 }, { - "name": "tests/integration/targets/win_agent_job/aliases", + "name": "tests/integration/targets/win_rg_resource_pool/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "80886616ffe77f72ad8654dd26e3c88268215eceda9fd2fcee6eb98288aadae1", + "chksum_sha256": "f514a090cace343c41b298fa180e6a993fc535cf9fd0498424e1db2f097261a4", "format": 1 }, { - "name": "tests/integration/targets/win_agent_job/meta", + "name": "tests/integration/targets/win_resource_governor", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_agent_job/meta/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "92d7d87955e27c2d9511ab6e1d62ecf60b9d0ed81895b1a5692c3cc620a29780", - "format": 1 - }, - { - "name": "tests/integration/targets/win_user", + "name": "tests/integration/targets/win_resource_governor/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_user/aliases", + "name": "tests/integration/targets/win_resource_governor/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4d4819a1314f1ea6a500be90e727a92fb9b964511644c7162c869e351037c2f2", - "format": 1 - }, - { - "name": "tests/integration/targets/win_user/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "da6570816fbce650c248033a1d6442e212b4d61baa00d6fbc449ae2e9b00777a", "format": 1 }, { - "name": "tests/integration/targets/win_user/meta/main.yml", + "name": "tests/integration/targets/win_resource_governor/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "805393b91b743ad8f62db1f7301c2c9c85cd78b64633986e456aa3add70d5419", + "chksum_sha256": "8f9e2da9d3feca4c1b60f565a53f4dc7e62f3a7eef4444e82b29d46d28c0bed3", "format": 1 }, { - "name": "tests/integration/targets/install_script", + "name": "tests/integration/targets/setup_sqlserver_test_plugins", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/install_script/files", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/vars", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/install_script/files/1-select-choice.sql", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/vars/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fde2acd9de812005948b5935c0c335889828e14ee58dbcc58a205096cdb2266f", + "chksum_sha256": "dae30dbe118009b07fecf11b4b0eb721706ce833d2f4ea1999bec0db5965de1e", "format": 1 }, { - "name": "tests/integration/targets/install_script/aliases", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/README.md", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "chksum_sha256": "6ee78c7c3661d0afd27fd340bbad2f302cf790e96b56911fd5b67761eab941f7", "format": 1 }, { - "name": "tests/integration/targets/install_script/tasks", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/install_script/tasks/main.yml", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "85e9885a3bb1a9621c0ac183c3c831efe453bbb5eddbb4d6351a620164b33672", + "chksum_sha256": "6e549bfeb53c72c6fc09b96c9d405f6b74d217080be03874c0ea6331af4b7e79", "format": 1 }, { - "name": "tests/integration/targets/install_script/meta", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/module_utils", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/install_script/meta/main.yml", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.ModuleUtils.AddType.psm1", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", - "format": 1 - }, - { - "name": "tests/integration/targets/win_traceflag", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "f87af398727a2cf732f475c988271054b15446abc32b0c615d7a26480b9e6f40", "format": 1 }, { - "name": "tests/integration/targets/win_traceflag/aliases", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.Basic.cs", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b60d4d845847bbd2c2a976e26c6d39e4943a1466503642ee370b84b634b07ed5", + "chksum_sha256": "8618a9a7d2dd6d22ae3479d1bcb1531da57eb978577ffbd79cbd7d7ca6b77e2d", "format": 1 }, { - "name": "tests/integration/targets/win_traceflag/meta", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/shell_plugins", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_traceflag/meta/main.yml", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/shell_plugins/pwsh.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7ff30f930e0f6004866fed58759768dfdda5f2354cea27c69d3a9636e7dcef02", + "chksum_sha256": "799d270e2028fccdc49b72338e0b2da17ed561e4f7e8deba52504ff6f4a12a56", "format": 1 }, { - "name": "tests/integration/targets/agent_job", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/connection_plugins", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/agent_job/aliases", + "name": "tests/integration/targets/setup_sqlserver_test_plugins/connection_plugins/local_pwsh.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "chksum_sha256": "d05e0a673b2b8e159c1ff114b18bd7176958446b079591cbdb05304c002bee4e", "format": 1 }, { - "name": "tests/integration/targets/agent_job/tasks", + "name": "tests/integration/targets/memory", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/agent_job/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "31c7e5478ab71d9b16cad90042519bd6cef26068f73dab84bf1b12fe6c6b1dcf", - "format": 1 - }, - { - "name": "tests/integration/targets/agent_job/meta", + "name": "tests/integration/targets/memory/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/agent_job/meta/main.yml", + "name": "tests/integration/targets/memory/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", - "format": 1 - }, - { - "name": "tests/integration/targets/setup_sqlserver_test_plugins", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "571c3ec667aa8c42235cf6a6d91e9ce5bcc8785653474f6a1d7bdd6166256705", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/shell_plugins", + "name": "tests/integration/targets/memory/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/shell_plugins/pwsh.py", + "name": "tests/integration/targets/memory/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ca3b46418c90e0d21b48a05afd0aeab5a62bc3b49311dd709d3468c34524829", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/README.md", + "name": "tests/integration/targets/memory/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6ee78c7c3661d0afd27fd340bbad2f302cf790e96b56911fd5b67761eab941f7", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/tasks", + "name": "tests/integration/targets/login", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "6e549bfeb53c72c6fc09b96c9d405f6b74d217080be03874c0ea6331af4b7e79", - "format": 1 - }, - { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/vars", + "name": "tests/integration/targets/login/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/vars/main.yml", + "name": "tests/integration/targets/login/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dae30dbe118009b07fecf11b4b0eb721706ce833d2f4ea1999bec0db5965de1e", + "chksum_sha256": "1439a3129965bb135085f89336b4fc48a1894bfd4f38f4bf8e68f164997fbc19", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/connection_plugins", + "name": "tests/integration/targets/login/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/connection_plugins/local_pwsh.py", + "name": "tests/integration/targets/login/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0156f30e8a101162732454cb62f5a072d412ab650cdb74b52724816ee466dddb", - "format": 1 - }, - { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/module_utils", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.ModuleUtils.AddType.psm1", + "name": "tests/integration/targets/login/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f87af398727a2cf732f475c988271054b15446abc32b0c615d7a26480b9e6f40", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.Basic.cs", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "8505c6c00f88db32518401563e3fd3d1b414cbe4ac1a79959d8e3773765d836a", + "name": "tests/integration/targets/win_ag_listener", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_hadr", + "name": "tests/integration/targets/win_ag_listener/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_hadr/aliases", + "name": "tests/integration/targets/win_ag_listener/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "823c89dbff7ce470f0ab6e7e3c41e7fa02b7b38fd4a1d5bcda2ecbcb98a4dbd7", + "chksum_sha256": "23fed7e50228fa01b7b19994f71440ad28b0684f89fd08f7906062fe77602421", "format": 1 }, { - "name": "tests/integration/targets/win_hadr/tasks", + "name": "tests/integration/targets/win_ag_listener/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_hadr/tasks/main.yml", + "name": "tests/integration/targets/win_ag_listener/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e5341d244291343a5efba167280a123556be0ce4480c8cab2282fc3e2c288609", - "format": 1 - }, - { - "name": "tests/integration/targets/win_hadr/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/win_hadr/meta/main.yml", + "name": "tests/integration/targets/win_ag_listener/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "823c89dbff7ce470f0ab6e7e3c41e7fa02b7b38fd4a1d5bcda2ecbcb98a4dbd7", "format": 1 }, { @@ -1974,13 +1757,6 @@ "chksum_sha256": null, "format": 1 }, - { - "name": "tests/integration/targets/first_responder_kit/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", - "format": 1 - }, { "name": "tests/integration/targets/first_responder_kit/tasks", "ftype": "dir", @@ -2010,523 +1786,418 @@ "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_step", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/first_responder_kit/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_step/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "47352893485e47a64c32139b049f01c0aa68e79591c0595922e0acffa2665523", + "name": "tests/integration/targets/win_traceflag", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_step/meta", + "name": "tests/integration/targets/win_traceflag/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_step/meta/main.yml", + "name": "tests/integration/targets/win_traceflag/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd6596491fb29701a783f70e0cc7e04bcb54c3af0306ff39166d7ffd01e57143", + "chksum_sha256": "7ff30f930e0f6004866fed58759768dfdda5f2354cea27c69d3a9636e7dcef02", "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_schedule", + "name": "tests/integration/targets/win_traceflag/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b60d4d845847bbd2c2a976e26c6d39e4943a1466503642ee370b84b634b07ed5", + "format": 1 + }, + { + "name": "tests/integration/targets/agent_job_schedule", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_schedule/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a5361cb2dc2de454e750c31de04aed891a17b82ae1d09ed36de2ce628e4f3542", - "format": 1 - }, - { - "name": "tests/integration/targets/win_agent_job_schedule/meta", + "name": "tests/integration/targets/agent_job_schedule/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_agent_job_schedule/meta/main.yml", + "name": "tests/integration/targets/agent_job_schedule/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "471a1229e4fd010cbc5f53e8f58a3816415bb9f7f3ff1b6a50d697c54ea52eeb", + "chksum_sha256": "2080e6f637f79d857797559778d18399d2d2c9adbc90992082851af7c76c5cd9", "format": 1 }, { - "name": "tests/integration/targets/win_backup", + "name": "tests/integration/targets/agent_job_schedule/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_backup/aliases", + "name": "tests/integration/targets/agent_job_schedule/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f4894d7d372026d355a62fe57e4c54da2b6588eb2df68b2bcfb3d6620525da09", - "format": 1 - }, - { - "name": "tests/integration/targets/win_backup/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/win_backup/meta/main.yml", + "name": "tests/integration/targets/agent_job_schedule/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9e6816dbbf21d3dba22fc22b8da0f0cc4cef6ac1dd82aefaab45a38c0fe3ecee", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/sa", + "name": "tests/integration/targets/win_database", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/sa/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", - "format": 1 - }, - { - "name": "tests/integration/targets/sa/tasks", + "name": "tests/integration/targets/win_database/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/sa/tasks/main.yml", + "name": "tests/integration/targets/win_database/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4ab5c5e605be645cc3e9b27e4c767366504d3191f99d9bb8aac1be6faea59e81", - "format": 1 - }, - { - "name": "tests/integration/targets/sa/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "c90756dd3934d30739814f2f25f6bed9190409f7134a21b6547594842dedeade", "format": 1 }, { - "name": "tests/integration/targets/sa/meta/main.yml", + "name": "tests/integration/targets/win_database/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "291c6f9c2e41aa8c04d6b8feb47807d97cdf9f02b487eb63f4507fbac044fae1", "format": 1 }, { - "name": "tests/integration/targets/win_maintenance_solution", + "name": "tests/integration/targets/setup_win_sqlserver", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_maintenance_solution/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "7d262d00ae91b2b827898ae863725e5579f68d3390fb255cc591560b4f616367", - "format": 1 - }, - { - "name": "tests/integration/targets/win_maintenance_solution/meta", + "name": "tests/integration/targets/setup_win_sqlserver/vars", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_maintenance_solution/meta/main.yml", + "name": "tests/integration/targets/setup_win_sqlserver/vars/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "51ae5e4c8a06b47364e63ec20fc30138f7d30ef5c0fda58701a248cdaad0481c", + "chksum_sha256": "f773fabf54dffb1da94c9a66e897675dd8831d87d1ff525edeaa581ac0963c7e", "format": 1 }, { - "name": "tests/integration/targets/win_ag_listener", + "name": "tests/integration/targets/setup_win_sqlserver/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_ag_listener/aliases", + "name": "tests/integration/targets/setup_win_sqlserver/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "823c89dbff7ce470f0ab6e7e3c41e7fa02b7b38fd4a1d5bcda2ecbcb98a4dbd7", + "chksum_sha256": "456a9ff2086b679cc9bca6d71da070006c67a8e121374985517c200734c42e97", "format": 1 }, { - "name": "tests/integration/targets/win_ag_listener/tasks", + "name": "tests/integration/targets/setup_win_sqlserver/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_ag_listener/tasks/main.yml", + "name": "tests/integration/targets/setup_win_sqlserver/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "23fed7e50228fa01b7b19994f71440ad28b0684f89fd08f7906062fe77602421", - "format": 1 - }, - { - "name": "tests/integration/targets/win_ag_listener/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "0717e3c911ac3a45ebb713a535b723d4ebc229a24910a45349c2e8f9ce88cae8", "format": 1 }, { - "name": "tests/integration/targets/win_ag_listener/meta/main.yml", + "name": "tests/integration/targets/setup_win_sqlserver/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "105c5f0785da8d117d54b796fedefa4ddbd7ec65b52058539abe49f327d06db8", "format": 1 }, { - "name": "tests/integration/targets/win_availability_group", + "name": "tests/integration/targets/backup", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_availability_group/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b522894638086953bde369a5f6c194a90c32338fefab24021b399659246ee20b", - "format": 1 - }, - { - "name": "tests/integration/targets/win_availability_group/tasks", + "name": "tests/integration/targets/backup/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_availability_group/tasks/main.yml", + "name": "tests/integration/targets/backup/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8f66aa5fd04f4ae573bafb0e037877232be65d063c0569b6a7fa9020081507c3", + "chksum_sha256": "78fe28d8507ece20158769c69efa631fdde989b9f2ef8d62cd5ac65e059eaa50", "format": 1 }, { - "name": "tests/integration/targets/win_availability_group/meta", + "name": "tests/integration/targets/backup/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_availability_group/meta/main.yml", + "name": "tests/integration/targets/backup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/win_database", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/win_database/aliases", + "name": "tests/integration/targets/backup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "291c6f9c2e41aa8c04d6b8feb47807d97cdf9f02b487eb63f4507fbac044fae1", + "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/win_database/meta", + "name": "tests/integration/targets/win_agent_job", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_database/meta/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c90756dd3934d30739814f2f25f6bed9190409f7134a21b6547594842dedeade", - "format": 1 - }, - { - "name": "tests/integration/targets/win_resource_governor", + "name": "tests/integration/targets/win_agent_job/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_resource_governor/aliases", + "name": "tests/integration/targets/win_agent_job/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8f9e2da9d3feca4c1b60f565a53f4dc7e62f3a7eef4444e82b29d46d28c0bed3", - "format": 1 - }, - { - "name": "tests/integration/targets/win_resource_governor/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "92d7d87955e27c2d9511ab6e1d62ecf60b9d0ed81895b1a5692c3cc620a29780", "format": 1 }, { - "name": "tests/integration/targets/win_resource_governor/meta/main.yml", + "name": "tests/integration/targets/win_agent_job/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "da6570816fbce650c248033a1d6442e212b4d61baa00d6fbc449ae2e9b00777a", + "chksum_sha256": "80886616ffe77f72ad8654dd26e3c88268215eceda9fd2fcee6eb98288aadae1", "format": 1 }, { - "name": "tests/integration/targets/dba_multitool", + "name": "tests/integration/targets/win_agent_job_schedule", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/dba_multitool/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", - "format": 1 - }, - { - "name": "tests/integration/targets/dba_multitool/tasks", + "name": "tests/integration/targets/win_agent_job_schedule/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/dba_multitool/tasks/main.yml", + "name": "tests/integration/targets/win_agent_job_schedule/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9c2dc342256920c670d472b94856269834490da88bd511ce501d7158dd080ecd", - "format": 1 - }, - { - "name": "tests/integration/targets/dba_multitool/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "471a1229e4fd010cbc5f53e8f58a3816415bb9f7f3ff1b6a50d697c54ea52eeb", "format": 1 }, { - "name": "tests/integration/targets/dba_multitool/meta/main.yml", + "name": "tests/integration/targets/win_agent_job_schedule/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "a5361cb2dc2de454e750c31de04aed891a17b82ae1d09ed36de2ce628e4f3542", "format": 1 }, { - "name": "tests/integration/targets/login", + "name": "tests/integration/targets/win_install_script", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/login/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", - "format": 1 - }, - { - "name": "tests/integration/targets/login/tasks", + "name": "tests/integration/targets/win_install_script/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/login/tasks/main.yml", + "name": "tests/integration/targets/win_install_script/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e43e68379e5d021d42afa83f87c2239ed1532ed52a0bba45a8bb0b5352193e9b", + "chksum_sha256": "f6dc29e973e9e7c8c7396cda456a513614d795455331165968588cbfc622726e", "format": 1 }, { - "name": "tests/integration/targets/login/meta", + "name": "tests/integration/targets/win_install_script/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/login/meta/main.yml", + "name": "tests/integration/targets/win_install_script/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", "format": 1 }, { - "name": "tests/integration/targets/win_tcp_port", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/win_tcp_port/aliases", + "name": "tests/integration/targets/win_install_script/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "823c89dbff7ce470f0ab6e7e3c41e7fa02b7b38fd4a1d5bcda2ecbcb98a4dbd7", "format": 1 }, { - "name": "tests/integration/targets/win_tcp_port/tasks", + "name": "tests/integration/targets/win_install_script/files", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_tcp_port/tasks/main.yml", + "name": "tests/integration/targets/win_install_script/files/1-select-choice.sql", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d692ce8436946b398e6cb3ff85f4c0e6a500468fb623d144566b25db71a60af5", + "chksum_sha256": "fde2acd9de812005948b5935c0c335889828e14ee58dbcc58a205096cdb2266f", "format": 1 }, { - "name": "tests/integration/targets/win_tcp_port/meta", + "name": "tests/integration/targets/nonquery", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_tcp_port/meta/main.yml", + "name": "tests/integration/targets/nonquery/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/nonquery/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "851bf7899fb14d2c976f6d2b1df869b108ab5f4440e2c57af920e06f7c59f07f", "format": 1 }, { - "name": "tests/integration/targets/maintenance_solution", + "name": "tests/integration/targets/nonquery/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/maintenance_solution/aliases", + "name": "tests/integration/targets/nonquery/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "format": 1 + }, + { + "name": "tests/integration/targets/nonquery/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/maintenance_solution/tasks", + "name": "tests/integration/targets/setup_sqlserver", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/maintenance_solution/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "d6841548d89da6e201186a5bd9ba2f370aff1ed3818fc9d5609a26a7405bd088", - "format": 1 - }, - { - "name": "tests/integration/targets/maintenance_solution/meta", + "name": "tests/integration/targets/setup_sqlserver/vars", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/maintenance_solution/meta/main.yml", + "name": "tests/integration/targets/setup_sqlserver/vars/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "79635f192493c32b61ca004b05e8445d822906b84321725bb94fee4eae0c69cd", "format": 1 }, { - "name": "tests/integration/targets/instance_info", + "name": "tests/integration/targets/setup_sqlserver/defaults", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/instance_info/aliases", + "name": "tests/integration/targets/setup_sqlserver/defaults/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "chksum_sha256": "454653b07873ad71128411eba4df7f2b86352fd4b884e667e045cab2b83ff4aa", "format": 1 }, { - "name": "tests/integration/targets/instance_info/tasks", + "name": "tests/integration/targets/setup_sqlserver/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/instance_info/tasks/main.yml", + "name": "tests/integration/targets/setup_sqlserver/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "22e5f3e538dfd862aebe6429f2d06293499bcd83a7b8da0f6afbee5f8033366b", + "chksum_sha256": "bd3b6c1bcc76af05949e4b6195b6674a7b5ff725b8e11e89cc09b2fa7828d815", "format": 1 }, { - "name": "tests/integration/targets/instance_info/meta", + "name": "tests/integration/targets/agent_job_step", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, - { - "name": "tests/integration/targets/instance_info/meta/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", - "format": 1 - }, - { - "name": "tests/integration/targets/agent_job_step", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/agent_job_step/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", - "format": 1 - }, { "name": "tests/integration/targets/agent_job_step/tasks", "ftype": "dir", @@ -2556,353 +2227,689 @@ "format": 1 }, { - "name": "tests/integration/targets/credential", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/credential/aliases", + "name": "tests/integration/targets/agent_job_step/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", "format": 1 }, { - "name": "tests/integration/targets/credential/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/.ansible-lint", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "982c0b7fe8683e818a27cf59b6a6892d91c277703c81e2db35994f63ef90e7fc", "format": 1 }, { - "name": "tests/integration/targets/credential/tasks/main.yml", + "name": "README.md", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "502c966d269ba16b8f50711aa3413b89361ca26241b95ea42bfadbb543078190", + "chksum_sha256": "0b860fe11d857950cb932384d69d836b52fa4aab697af697b2f74ccfe792160e", "format": 1 }, { - "name": "tests/integration/targets/credential/meta", + "name": "docs", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/credential/meta/main.yml", + "name": "docs/.gitkeep", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", - "format": 1 - }, - { - "name": "tests/integration/targets/agent_job_category", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "chksum_sha256": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b", "format": 1 }, { - "name": "tests/integration/targets/agent_job_category/aliases", + "name": "ADOPTERS.md", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "chksum_sha256": "fe2c96f3cddb707c41ef291696c57c8766303500e26218f725657bd39cedd601", "format": 1 }, { - "name": "tests/integration/targets/agent_job_category/tasks", + "name": "changelogs", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/agent_job_category/tasks/main.yml", + "name": "changelogs/changelog.yaml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0544826a56fa9285258e41f18f989bad46a9a333c4508b6ff52991cb820ef6dd", + "chksum_sha256": "6397d8c6b1b5bf3d2ff546e6aaebfef0bfd3165fe29514018937c098c6b4d890", "format": 1 }, { - "name": "tests/integration/targets/agent_job_category/meta", + "name": "changelogs/fragments", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/agent_job_category/meta/main.yml", + "name": "changelogs/fragments/.keep", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "format": 1 }, { - "name": "tests/integration/targets/win_instance_info", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "changelogs/config.yaml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1e054fb68c58140c282fbaf0150eee1bf80ad925196dddd74e848e91b7315a1e", "format": 1 }, { - "name": "tests/integration/targets/win_instance_info/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "96874064bd5afc3782b688417ee53a256f2aeee2b3f7be9db26ef14760752d33", + "name": "plugins", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_instance_info/meta", + "name": "plugins/module_utils", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/win_instance_info/meta/main.yml", + "name": "plugins/module_utils/_SqlServerUtils.psm1", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ce5de48e8e8a42b74d629f088dc4e10650fe45b811ef394b852884e11ac3d20b", + "chksum_sha256": "4fdfc528ea4a54118f616738c9630066e47e0d010c2b60cbecd851a5b5547c3f", "format": 1 }, { - "name": "tests/integration/targets/database", + "name": "plugins/modules", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/database/aliases", + "name": "plugins/modules/dba_multitool.ps1", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "chksum_sha256": "5e13bd1112019e1852969d1b39b8579abea06a8d4a7742feb4664c637865b9f5", "format": 1 }, { - "name": "tests/integration/targets/database/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/user.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f3c923f60de426d3b12e67709d0edcec86a396163a9911af82ad937c5561a7bc", "format": 1 }, { - "name": "tests/integration/targets/database/tasks/main.yml", + "name": "plugins/modules/first_responder_kit.ps1", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "096c592c99e22c947444c3cefe3007bdc7b6370b7c814b0c6cc0e8bd1b6f77c5", + "chksum_sha256": "1e478006b282e7dfc5ebbdf5045f6a81b632cbe2c70819aca11de40dc4de3364", "format": 1 }, { - "name": "tests/integration/targets/database/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/sp_configure.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9c7d49cb933f7d1128be15e359e2ac4f7d8fd48facb741d7c5866ac4028b16c5", "format": 1 }, { - "name": "tests/integration/targets/database/meta/main.yml", + "name": "plugins/modules/backup.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "ddffc896a151a1c0a9d1798d1f7796d49aae2886f5aeb9c07ca72378d257a298", "format": 1 }, { - "name": "tests/integration/targets/backup", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/agent_job_schedule.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "195f583bfb2e1b068f3022bd0a152fde686581266154973f43f150d10adbe247", "format": 1 }, { - "name": "tests/integration/targets/backup/aliases", + "name": "plugins/modules/ag_replica.ps1", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "chksum_sha256": "5868def510947485eea9e2f495ed80cfb407db89c6d9f42c829a45eeb00a9ad1", "format": 1 }, { - "name": "tests/integration/targets/backup/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/install_script.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0e23cd11873aa61dcfbe61ab841e54e31d07d97bc8c5b44c7623c097c90b5621", "format": 1 }, { - "name": "tests/integration/targets/backup/tasks/main.yml", + "name": "plugins/modules/hadr.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "78fe28d8507ece20158769c69efa631fdde989b9f2ef8d62cd5ac65e059eaa50", + "chksum_sha256": "b2017667c8e572a1582cb076b3d543f4d7eba1ed6d66a7c0249d48b4f793868a", "format": 1 }, { - "name": "tests/integration/targets/backup/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/resource_governor.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a30e5d126462c9fc8b882307851d623267308c7c6fb4eaac51ce51cff6fa415d", "format": 1 }, { - "name": "tests/integration/targets/backup/meta/main.yml", + "name": "plugins/modules/credential.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "16a49e24a042e89e609a22adc1316559025f60bf24fb456c0acda09e611b6ec5", "format": 1 }, { - "name": "tests/integration/targets/agent_job_schedule", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/traceflag.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "278f6beedbef5c73eaf3b98d04dc1adda8a0921aa48a138f339c8d25747cedb9", "format": 1 }, { - "name": "tests/integration/targets/agent_job_schedule/aliases", + "name": "plugins/modules/availability_group.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79821e9e38c38952ccfdbe45b988082364c67d537d5753dfbb0a5f8716c48ab9", + "chksum_sha256": "8b3b47b92e9a558181210ab01de6d6637d3b39d61d647630926ac424a08303ef", "format": 1 }, { - "name": "tests/integration/targets/agent_job_schedule/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/nonquery.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "28566664f6a3f97f72301bc34fa22af1421ead1ca572d651f241e960acc2be29", "format": 1 }, { - "name": "tests/integration/targets/agent_job_schedule/tasks/main.yml", + "name": "plugins/modules/memory.ps1", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "30a85b8a191383a79170a54c720a886e461ac3ac35a69ef79920b5fb6aef7447", + "chksum_sha256": "de05b5612d9e692126afe9a25841d3dcbcfef1079cb45585d49564cd3bac2fc6", "format": 1 }, { - "name": "tests/integration/targets/agent_job_schedule/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/spn.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f3eb83933723cbc2f88238a60cdb539b97576e9feb5ca0543da2b561e2e60b83", "format": 1 }, { - "name": "tests/integration/targets/agent_job_schedule/meta/main.yml", + "name": "plugins/modules/dba_multitool.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "0236dc7ccb91ecf1e0fdb832a40a8f82ed90ad888d7e02f41b7a2848ddc48bef", "format": 1 }, { - "name": "tests/integration/targets/win_ag_replica", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/sa.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "984966ae91f444089b89a510f47de10b80d3417bd2def60af3bc91a5ba5979d1", "format": 1 }, { - "name": "tests/integration/targets/win_ag_replica/aliases", + "name": "plugins/modules/user.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b522894638086953bde369a5f6c194a90c32338fefab24021b399659246ee20b", + "chksum_sha256": "99b2b1074ac11298c64b987414934b55e1e95a482bcc3185285662482dbf55b7", "format": 1 }, { - "name": "tests/integration/targets/win_ag_replica/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/maintenance_solution.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b2b43694b89c22938156682c8c6f1b3a30c3a0b67f7f50e37efcd17e1eb1cde5", "format": 1 }, { - "name": "tests/integration/targets/win_ag_replica/tasks/main.yml", + "name": "plugins/modules/nonquery.ps1", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d2635b4ff57bb61b0691b4577c5c8ab6dae4dd5a8f815d00abf9d849695cb392", + "chksum_sha256": "e098278136eec42260b9354b6dca6816f4968c546f12e259cd2e62d2f4a72e82", "format": 1 }, { - "name": "tests/integration/targets/win_ag_replica/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/agent_job.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "19ab20059fbd77950f856cb7be75049136673d2c793f91900be18b194716b97a", "format": 1 }, { - "name": "tests/integration/targets/win_ag_replica/meta/main.yml", + "name": "plugins/modules/traceflag.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a170d576026b40f2e8d93ced0dcaff0108bd61e8f9d62bc3bee3bb14dba13b83", + "chksum_sha256": "d08e57033e0da3f63f1c024446f02abdff41400dd0607a400f234468e05260ff", "format": 1 }, { - "name": "tests/integration/targets/win_memory", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/ag_listener.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5fb3935cf9a93b88546cbc762ce8825df079013d679af682626a9a8de5d003e4", "format": 1 }, { - "name": "tests/integration/targets/win_memory/aliases", + "name": "plugins/modules/database.ps1", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "29e8c25ab424e16e434d902ced6f408da8a4f1f9363126caa03092f62bcb43aa", + "chksum_sha256": "eaedf444462b956cba62cf1742f07353950ccab565377191fcde24241cdb5690", "format": 1 }, { - "name": "tests/integration/targets/win_memory/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/sp_whoisactive.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "26025dd39dc4bea36f72bcb0dd4a279245adde8e6be4792cc40ef90d02ade8e7", "format": 1 }, { - "name": "tests/integration/targets/win_memory/meta/main.yml", + "name": "plugins/modules/hadr.ps1", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c32e78042afc05d5738763ed9a9281f6e6a5e03231c2124087400143409ec6d6", + "chksum_sha256": "ae6aa285169947e898e685a1125017bcc755fcbb578dd5f1654da4631576ad5b", "format": 1 }, { - "name": "tests/integration/inventory", + "name": "plugins/modules/restore.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0a28c1f749c45ff439aeeb826635429412f65c284d7d52ca7ff51b9dde495551", + "chksum_sha256": "0f357dea6f735aae072bfee1d35335140a2a4cf3ac617ee68347cde8f7991bad", "format": 1 }, { - "name": "tests/integration/inventory.winrm.ci", + "name": "plugins/modules/spn.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d1a9b5a526214d256d89f06ac3180e7d73b63b7cd199a536888405e21f8768de", + "chksum_sha256": "57a8e8f95263b83394aaf4342759ffccbfa20315cf8d208aecee5b54f46d7a72", "format": 1 }, { - "name": ".vscode", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/tcp_port.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fcb5a1326cf73886733d6772f7623bd7e792563155c8d72a0d59312998215d91", "format": 1 }, { - "name": ".vscode/extensions.json", + "name": "plugins/modules/agent_job_step.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f72b83e1aa1301adb18ce0fe71ce6613d3cfb148f881b3e39c55359d41d3277f", + "chksum_sha256": "56da01e0ba38203752b396a705ef7b385109c803de9787456ab9446353ef88db", "format": 1 }, { - "name": ".vscode/settings.json", + "name": "plugins/modules/ag_replica.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "129f69fd05d6feacc20ea9f2edf00332ce20639fa3c35f4f4b0a42dea2835bac", + "chksum_sha256": "3d7f122d89145949eaeabf78c2e4747ba9158611d9dd28efe19a6c23b61a18cf", "format": 1 }, { - "name": "CHANGELOG.rst", + "name": "plugins/modules/ag_listener.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c91b831040e354aff0581367dcd1778b898ca424a92abf35786e9835e96c1018", + "format": 1 + }, + { + "name": "plugins/modules/sa.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "950e4b60caa84225b0153cf08fe8b87ca97a27f155fc1d4a1d95c5d677ea0622", + "format": 1 + }, + { + "name": "plugins/modules/instance_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c6d60a465bcc5ab23e0ab7688479f2c54ca80c4d15f9a7a6adc0211f8aabd4fd", + "format": 1 + }, + { + "name": "plugins/modules/instance_info.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "afe3b3ee537cfe249f987e961eb1860ad5c01f617caf756a2d6c204357e25d11", + "format": 1 + }, + { + "name": "plugins/modules/sp_configure.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2715043d68e455a59bd7ff7028c769c23d662ae04b937128aec461a39c544bf5", + "format": 1 + }, + { + "name": "plugins/modules/rg_resource_pool.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8bda00accf8650882d9527b1537db36a68d9eafa1f2345f844d7ac59ac1d003c", + "format": 1 + }, + { + "name": "plugins/modules/rg_resource_pool.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a18afaa50ed7d7183a0a9458b8b4a62130d92670f5d68197c8272c498eef876e", + "format": 1 + }, + { + "name": "plugins/modules/sp_whoisactive.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6d8e9698a0715ede939c5ec6b1bb786c99f63221d3b2c2f91f8b6fafd488a9a5", + "format": 1 + }, + { + "name": "plugins/modules/agent_job_step.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3ab30f960d4e24bcb1a2dcb22d5a57183eba5c22811f6bc2d7222791103660b1", + "format": 1 + }, + { + "name": "plugins/modules/maintenance_solution.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "126a8b7ea648ab2bc6e36db65a9b5ca85ca1c2224ad21445c176ea700b5a00ad", + "format": 1 + }, + { + "name": "plugins/modules/availability_group.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "46d7f93e5951ea8096b4632ffc8b2bed5391dcb28a7b1c2ed66d9dfc5eb3ec3a", + "format": 1 + }, + { + "name": "plugins/modules/login.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8810d99eb07f72104830e9d0741fa93c915e0ab238f932dbbea90882030330b7", + "format": 1 + }, + { + "name": "plugins/modules/agent_job.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9476d4b38459e10be25b64c96bf7b2b9bb4f49045d15cd36f959737eec194d34", + "format": 1 + }, + { + "name": "plugins/modules/database.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "943ace13f44fc4e582ed5bf7c6064b4c90680c2580169782d3c7c61845816b8a", + "format": 1 + }, + { + "name": "plugins/modules/agent_job_schedule.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ec152ec9b41bdeabfb3289c73b4c19955b7b1d849420e93513bd10640e2824c4", + "format": 1 + }, + { + "name": "plugins/modules/backup.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c31187c932814a34e5f46576e9ec68237969390de4377e3baa35598940f2fe36", + "format": 1 + }, + { + "name": "plugins/modules/install_script.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6932f5d090a894e3bef5e29f612bd1545aae360d91f8ffc85c7352a5da1548db", + "format": 1 + }, + { + "name": "plugins/modules/resource_governor.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "27d1f38306c23bfea82dc745425cf6cef0099156054bee4a497d0687866ade97", + "format": 1 + }, + { + "name": "plugins/modules/memory.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1c3e840a66bb01f5b809b7c9347594cfed73286cb589ca710eb3802f990fe9c8", + "format": 1 + }, + { + "name": "plugins/modules/rg_workload_group.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9faacfc40d32dbcc2eae198f15784613d7b20721045f9bc551be139019fe2027", + "format": 1 + }, + { + "name": "plugins/modules/agent_job_category.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "22167936fa56c583e687b1feaa79d42d3d6fe99832c3fba0f818e8e212820f45", + "format": 1 + }, + { + "name": "plugins/modules/login.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "196042ab05e84d23b632c7a2d3ca39b6eb4e96f366e3e1dff8119441f4f7b7c2", + "format": 1 + }, + { + "name": "plugins/modules/credential.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "364bcb3116174488c1a1c51ada8eac915e9893434dd85577ea49d49c781a8e83", + "format": 1 + }, + { + "name": "plugins/modules/restore.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c5544cbbca85e97df2d855e33c64ef045d49a441410a6cc3b0a9328ab991485d", + "format": 1 + }, + { + "name": "plugins/modules/agent_job_category.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "eda9101228bdf9db6dfce794c3d7cb51b2913f43cbfd6d2045179a74dad4f52e", + "format": 1 + }, + { + "name": "plugins/modules/tcp_port.ps1", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "82354c3a07f163d733ba25a8e43c185ae890681e1104df0224fdbfa68da26c8f", + "format": 1 + }, + { + "name": "plugins/modules/rg_workload_group.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9f5ed35870b957394be3dca618c29c35bdf6628666678226aae495cdd366b6e8", + "chksum_sha256": "90cae13aa924431ceddce76eb94f49576b4e8396227a141a2d81c9fbf5f9dd34", + "format": 1 + }, + { + "name": "plugins/modules/first_responder_kit.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "bf16bc535cfa590e884e99e3c406c602aca4c1322b9a9c86679d1980f18e5e1a", + "format": 1 + }, + { + "name": "plugins/doc_fragments", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/doc_fragments/attributes.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cdffff9cfa27f07533b806e63d11b9a752144eb5f2d7d8c8837e7a4efa4da4c7", + "format": 1 + }, + { + "name": "plugins/doc_fragments/state.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ae0b5a340638525f1d65822b592ccba03c72dd937e8f1f60f41539f80a1af2f7", + "format": 1 + }, + { + "name": "plugins/doc_fragments/sql_credentials.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8319c0f26d235fb9dd33444fe7cfe963324207e64f77423098fb0a6c071be791", + "format": 1 + }, + { + "name": ".github", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github/ISSUE_TEMPLATE", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github/ISSUE_TEMPLATE/bug_report.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8d3db528d29f10782cc5b08a68999c7144efbeaa6724817d6c72a69f4c745a31", + "format": 1 + }, + { + "name": ".github/ISSUE_TEMPLATE/feature_request.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cd5b39aee355194f532b686c62a783c0657d8f7810586a757775769b291461a2", + "format": 1 + }, + { + "name": ".github/workflows", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": ".github/workflows/ansible-test-windows.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9f1e8d195386bbda824f1b666b84c1ecfe75c3f7e83ae325a715b5189e733e3e", + "format": 1 + }, + { + "name": ".github/workflows/docs-pr.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "84a88873a148150b9b42877fa1c42697c05f631e39e618160bd99bf0f3652abd", + "format": 1 + }, + { + "name": ".github/workflows/release.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c7da1e4ae99e0dee4bebf9b7b709a90bfda092ff8c3a421f21da5f39d1251d36", + "format": 1 + }, + { + "name": ".github/workflows/ansible-test.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "104a40d59c18f8ca86b4cc4fe122e801b95c634bf3a0af9087734154893b63e3", + "format": 1 + }, + { + "name": ".github/workflows/docs-push.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9529da03eea03a258ab7ec8613310e62ad06fdbadd293d575070797d716443e9", + "format": 1 + }, + { + "name": ".github/PULL_REQUEST_TEMPLATE.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4ea1170a9065ecc1b0effb0e52f06fe42ef9936e86dfddb21c43efdd1c929b7b", + "format": 1 + }, + { + "name": ".github/codecov.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a42ee6fd570c21e6f7828ebb71585d819fd3fa126b3d98c39ea79565ce1a0ed6", + "format": 1 + }, + { + "name": ".github/FUNDING.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1a09efd96d758af083de6b9468b6508672806abb882fd9fc16a1a23a67ab3acc", + "format": 1 + }, + { + "name": ".github/dependabot.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a35bab1dd3e838ca5730aae35e4b127a052f8e03d5ed5437549e95f8424e621c", + "format": 1 + }, + { + "name": ".github/in-solidarity.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "43f54d1f6c1496d0a02ce3144f73d479f2e37ea3d2bb9e54ba08763ddfd230a2", + "format": 1 + }, + { + "name": "CODE_OF_CONDUCT.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "14ec928234a7ed52bf8b458d31e4862335111e477e4dbe7fb543686c24115140", + "format": 1 + }, + { + "name": "meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "meta/runtime.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "94d6b49778d101cca4b6cdfc026e86ba673af5cb029165c3dd170f3123b62286", + "format": 1 + }, + { + "name": "MAINTAINERS", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "29b1b04e645e0c11e59c48cfe7bac3dbe16f787a9d6114847d9a5c3b5990e731", "format": 1 } ], diff --git a/ansible_collections/lowlydba/sqlserver/MANIFEST.json b/ansible_collections/lowlydba/sqlserver/MANIFEST.json index 8ce4fe513..e4601206f 100644 --- a/ansible_collections/lowlydba/sqlserver/MANIFEST.json +++ b/ansible_collections/lowlydba/sqlserver/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "lowlydba", "name": "sqlserver", - "version": "1.3.1", + "version": "2.3.2", "authors": [ "John McCall (github.com/lowlydba)" ], @@ -25,7 +25,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "84cd6ed3f803e766ba81e7a8b79a2347820c2c28333e7720260378cfcb58831d", + "chksum_sha256": "c715ba466fb55aea6acf9408f6c7f1286005dda30e44d773afa17e8a32e5ab03", "format": 1 }, "format": 1 diff --git a/ansible_collections/lowlydba/sqlserver/README.md b/ansible_collections/lowlydba/sqlserver/README.md index 8b0b7873f..3de850744 100644 --- a/ansible_collections/lowlydba/sqlserver/README.md +++ b/ansible_collections/lowlydba/sqlserver/README.md @@ -1,4 +1,4 @@ -# lowlydba.sqlserver Collection for Ansible +# lowlydba.sqlserver Collection for Ansible ![GPL v3](https://img.shields.io/github/license/lowlydba/lowlydba.sqlserver) [![CI](https://github.com/lowlydba/lowlydba.sqlserver/actions/workflows/ansible-test.yml/badge.svg)](https://github.com/lowlydba/lowlydba.sqlserver/actions/workflows/ansible-test.yml) @@ -11,11 +11,17 @@ - [Contributing to this collection](#contributing-to-this-collection) - [Collection maintenance](#collection-maintenance) - [Tested with](#tested-with) + - [Ansible](#ansible) + - [SQL Server](#sql-server) - [External requirements](#external-requirements) - [Using this collection](#using-this-collection) - [Installing the Collection from Ansible Galaxy](#installing-the-collection-from-ansible-galaxy) -- [Release notes](#release-notes) - [Releasing](#releasing) + - [Release notes](#release-notes) + - [Next Release](#next-release) + - [Schedule](#schedule) + - [Versioning](#versioning) + - [Deprecation](#deprecation) ## Modules @@ -59,10 +65,9 @@ To learn how to maintain / become a maintainer of this collection, refer to the ### Ansible -- 2.11 -- 2.12 - 2.13 - 2.14 +- 2.15 - dlevel ### SQL Server @@ -73,8 +78,8 @@ To learn how to maintain / become a maintainer of this collection, refer to the ## External requirements - PowerShell modules - - [dbatools][dbatools] >= 1.1.112 - - [dbops][dbops] >= 0.8.0 + - [dbatools][dbatools] >= 2.0.0 + - [dbops][dbops] >= 0.9.0 ## Using this collection diff --git a/ansible_collections/lowlydba/sqlserver/changelogs/changelog.yaml b/ansible_collections/lowlydba/sqlserver/changelogs/changelog.yaml index 33237c7b7..57c71a1e5 100644 --- a/ansible_collections/lowlydba/sqlserver/changelogs/changelog.yaml +++ b/ansible_collections/lowlydba/sqlserver/changelogs/changelog.yaml @@ -405,3 +405,92 @@ releases: - 167-update-login-docs.yml - fix_sa.yml release_date: '2022-12-18' + 2.0.0: + changes: + breaking_changes: + - Updating minimum DBATools version to v2.0.0 to allow for pwsh 7.3+ compatibility. + There may also be breaking change behavior in DBATools, see https://blog.netnerds.net/2023/03/whats-new-dbatools-2.0/. + (https://github.com/lowlydba/lowlydba.sqlserver/pull/181) + release_summary: A major version bump of DBATools to version 2+. This will guarantee + compatibility with PowerShell Core versions 7.3+ and future SQL Server versions. + For more information on that release, see https://blog.netnerds.net/2023/03/whats-new-dbatools-2.0/. + Outside of major problems, new changes to this collection will not be backported + to v1. + fragments: + - dbatools-v2.yml + - release-summary-v2.yml + release_date: '2023-04-30' + 2.1.0: + changes: + minor_changes: + - Add refresh workaround for agent schedule bug where properties returned are + stale. (https://github.com/lowlydba/lowlydba.sqlserver/pull/185) + - Added SID as an optional parameter to the login module (https://github.com/lowlydba/lowlydba.sqlserver/pull/189) + release_summary: Add sid to login, thanks @OsirisDBA! + fragments: + - 185-fix-agent-schedule.yml + - 189-add-sid-to-login.yml + - 2-1-0-release.yml + release_date: '2023-08-11' + 2.2.0: + changes: + minor_changes: + - Added only_accessible as an optional parameter to the database module (https://github.com/lowlydba/lowlydba.sqlserver/pull/198) + release_summary: Bug fix in the database module. + fragments: + - 198-add-onlyaccessible-param-to-database.yml + - 2-2-0-release-summary.yml + release_date: '2023-08-26' + 2.2.1: + changes: + minor_changes: + - Fixes error handling for Remove-DbaDatabase when joined to AvailabilityGroup, + exception was not being thrown so we have to parse Status + release_summary: Bugfix for database module in the context of availability groups. + fragments: + - 2-2-1-release-summary.yml + - 200-remove-dbadatabase-exception-handling.yml + release_date: '2023-08-29' + 2.2.3: + changes: + bugfixes: + - Add ActiveStartDate to the compare properties so this item is marked accurately + as changed. + - Fixed the formatting of the SPN by updating the backslash to a forward-slash + for the $spn var (lowlydba.sqlserver.spn) + release_summary: Minor bugfixes. + fragments: + - 214-fix-schedule-activestartdate.yml + - 219-spn-format-fix.yml + - release-summary-2-2-3.yml + release_date: '2024-02-07' + 2.3.0: + changes: + minor_changes: + - Add ability to prevent changing login's password, even if password supplied. + release_summary: New feature from @OsirisDBA for skipping login password resets! + fragments: + - 2-2-4-release-summary.yml + - 227-skip-pwd-reset.yml + release_date: '2024-02-10' + 2.3.1: + changes: + minor_changes: + - Add new input strings to be compatible with dbops v0.9.x (https://github.com/lowlydba/lowlydba.sqlserver/pull/231) + release_summary: Update the install script feature to accommodate the latest + minor DbOps release (v0.9.x) + fragments: + - 2-3-1-release-summary.yml + - 231-dbops-v09.yml + release_date: '2024-02-24' + 2.3.2: + changes: + bugfixes: + - Update documentation for agent_job_schedule to reflect proper input formatting. + (https://github.com/lowlydba/lowlydba.sqlserver/pull/229) + release_summary: Small fix for documentation and upstream fix available in dbatools + v2.1.9. + fragments: + - 2-3-2-release-summary.yml + - 229-docs-update.yml + release_date: '2024-03-09' diff --git a/ansible_collections/lowlydba/sqlserver/meta/runtime.yml b/ansible_collections/lowlydba/sqlserver/meta/runtime.yml index 03c25c9ac..96a9ee519 100644 --- a/ansible_collections/lowlydba/sqlserver/meta/runtime.yml +++ b/ansible_collections/lowlydba/sqlserver/meta/runtime.yml @@ -1,2 +1,2 @@ --- -requires_ansible: ">=2.11" +requires_ansible: ">=2.12" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/ag_listener.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/ag_listener.ps1 index dd377141b..e20238ed4 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/ag_listener.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/ag_listener.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" @@ -63,7 +63,7 @@ try { $output = Add-DbaAgListener @listenerParams $module.Result.changed = $true } - elseif ($existingListener.Port -ne $port) { + elseif ($existingListener.PortNumber -ne $port) { $output = Set-DbaAgListener -AvailabilityGroup $agName -Listener $listenerName -Port $port $module.Result.changed = $true } diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/ag_replica.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/ag_replica.ps1 index cd7d09306..7a9fde0cc 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/ag_replica.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/ag_replica.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job.ps1 index cf261f3e2..b1b6df7aa 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_category.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_category.ps1 index 1e5c033a9..da7b16edb 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_category.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_category.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_schedule.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_schedule.ps1 index 6681dcffd..62b22591c 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_schedule.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_schedule.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" @@ -113,7 +113,7 @@ try { $compareProperty = @( "ActiveEndDate" "ActiveEndTimeOfDay" - "ActiveEndTimeOfDay" + "ActiveStartDate" "ActiveStartTimeOfDay" "Description" "FrequencyInterval" @@ -138,6 +138,12 @@ try { # Create schedule else { $output = New-DbaAgentSchedule @scheduleParams + if ($null -ne $job) { + # https://github.com/dataplat/dbatools/issues/8933 + if ($null -ne $output -and ($null -ne ($output | Get-Member -Name 'Refresh'))) { + $output.Refresh() + } + } $module.Result.changed = $true } } diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_schedule.py b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_schedule.py index 008efca2a..cb0232ad0 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_schedule.py +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_schedule.py @@ -80,17 +80,18 @@ options: start_date: description: - The date on which execution of a job can begin. - - If I(force=true)the start date will be the current day. - - Format is C(YYYY-MM-DD). + - If I(force=true) the start date will be the current day. + - Format is C(yyyyMMdd). type: str required: false end_date: description: - The date on which execution of a job can stop. - - If I(force=true) the end date will be C(9999-12-31). - - Format is C(YYYY-MM-DD). + - If I(force=true) the end date will be C(99991231), via dbatools. + - Format is C(yyyyMMdd). type: str required: false + start_time: description: - The time on any day to begin execution of a job. Format C(HHMMSS) (24 hour clock). diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_step.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_step.ps1 index 1bbbeb2e1..b5691ca2a 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_step.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/agent_job_step.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/availability_group.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/availability_group.ps1 index 177a6d109..94c872aeb 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/availability_group.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/availability_group.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/backup.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/backup.ps1 index 163d45036..4f2e3eafe 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/backup.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/backup.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/credential.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/credential.ps1 index 29631b11a..7989fce8e 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/credential.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/credential.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/database.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/database.ps1 index 4c3e3c9d0..dc030946c 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/database.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/database.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" @@ -22,6 +22,7 @@ $spec = @{ secondary_maxdop = @{type = 'int'; required = $false; } compatibility = @{type = 'str'; required = $false; } rcsi = @{type = 'bool'; required = $false; } + only_accessible = @{type = 'bool'; default = 'true' } state = @{type = 'str'; required = $false; default = 'present'; choices = @('present', 'absent') } } } @@ -35,6 +36,7 @@ $logFilePath = $module.Params.log_file_path $owner = $module.Params.owner $compatibility = $module.Params.compatibility [nullable[bool]]$rcsiEnabled = $module.Params.rcsi +[nullable[bool]]$onlyAccessible = $module.Params.only_accessible [nullable[int]]$maxDop = $module.Params.maxdop [nullable[int]]$secondaryMaxDop = $module.Params.secondary_maxdop $state = $module.Params.state @@ -48,7 +50,7 @@ try { SqlInstance = $sqlInstance SqlCredential = $sqlCredential Database = $database - OnlyAccessible = $true + OnlyAccessible = $onlyAccessible ExcludeSystem = $true EnableException = $true } @@ -61,8 +63,18 @@ try { if ($state -eq "absent") { if ($null -ne $existingDatabase) { - $existingDatabase | Remove-DbaDatabase -WhatIf:$checkMode -EnableException -Confirm:$false - $module.Result.changed = $true + try { + $droppedDatabase = $existingDatabase | Remove-DbaDatabase -WhatIf:$checkMode -EnableException -Confirm:$false + if ($droppedDatabase.Status -eq "Dropped") { + $module.Result.changed = $true + } + elseif ($droppedDatabase.Status -ne "Dropped") { + $module.FailJson("Database [$database] was not dropped. " + $droppedDatabase.Status) + } + } + catch { + $module.FailJson("An exception occurred while trying to drop database [$database].", $_) + } } $module.ExitJson() } diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/database.py b/ansible_collections/lowlydba/sqlserver/plugins/modules/database.py index 97551c718..d1d8cd91d 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/database.py +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/database.py @@ -61,6 +61,13 @@ options: - Whether or not to enable Read Committed Snapshot Isolation. required: false type: bool + only_accessible: + description: + - Whether or not to enable Read Committed Snapshot Isolation. + default: true + required: false + type: bool + version_added: '2.2.0' author: "John McCall (@lowlydba)" requirements: - L(dbatools,https://www.powershellgallery.com/packages/dbatools/) PowerShell module diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/dba_multitool.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/dba_multitool.ps1 index ef52bdd6d..931c8f2c3 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/dba_multitool.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/dba_multitool.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" $spec = @{ diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/first_responder_kit.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/first_responder_kit.ps1 index 1e19ce62f..8a50f3ae5 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/first_responder_kit.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/first_responder_kit.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" $spec = @{ diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/hadr.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/hadr.ps1 index 473ad4802..96a3e0e89 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/hadr.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/hadr.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/install_script.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/install_script.ps1 index 5c26588eb..ae552f486 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/install_script.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/install_script.ps1 @@ -6,8 +6,8 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } -#Requires -Modules @{ ModuleName="dbops"; ModuleVersion="0.8.0" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } +#Requires -Modules @{ ModuleName="dbops"; ModuleVersion="0.9.0" } $spec = @{ supports_check_mode = $true @@ -15,7 +15,7 @@ $spec = @{ database = @{type = 'str'; required = $true } path = @{type = 'str'; required = $true } deployment_method = @{type = 'str'; required = $false; default = 'NoTransaction' - choices = @('NoTransaction', 'SingleTransaction', 'TransactionPerScript') + choices = @('NoTransaction', 'SingleTransaction', 'TransactionPerScript', 'AlwaysRollback') } schema_version_table = @{type = 'str'; required = $false } no_log_version = @{type = 'bool'; required = $false; default = $false } diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/install_script.py b/ansible_collections/lowlydba/sqlserver/plugins/modules/install_script.py index 4dbf78f41..d233fb7bd 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/install_script.py +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/install_script.py @@ -33,10 +33,11 @@ options: - C(SingleTransaction) - wrap all the deployment scripts into a single transaction and rollback whole deployment on error. - C(TransactionPerScript) - wrap each script into a separate transaction; rollback single script deployment in case of error. - C(NoTransaction) - deploy as is. + - C(AlwaysRollback) - roll back the transaction. type: str required: false default: 'NoTransaction' - choices: ['NoTransaction', 'SingleTransaction', 'TransactionPerScript'] + choices: ['NoTransaction', 'SingleTransaction', 'TransactionPerScript', 'AlwaysRollback'] no_log_version: description: - If set, the deployment will not be tracked in the database. That will also mean that all the scripts diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/instance_info.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/instance_info.ps1 index a99ea01de..61d096926 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/instance_info.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/instance_info.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/login.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/login.ps1 index d509ba794..4edf5b323 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/login.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/login.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" @@ -21,6 +21,8 @@ $spec = @{ password_must_change = @{type = 'bool'; required = $false } password_policy_enforced = @{type = 'bool'; required = $false } password_expiration_enabled = @{type = 'bool'; required = $false } + sid = @{type = 'str'; required = $false } + skip_password_reset = @{type = 'bool'; required = $false; default = $false } state = @{type = 'str'; required = $false; default = 'present'; choices = @('present', 'absent') } } } @@ -37,6 +39,8 @@ $language = $module.Params.language [nullable[bool]]$passwordMustChange = $module.Params.password_must_change [nullable[bool]]$passwordExpirationEnabled = $module.Params.password_expiration_enabled [nullable[bool]]$passwordPolicyEnforced = $module.Params.password_policy_enforced +[nullable[bool]]$skip_password_reset = $module.Params.skip_password_reset +$sid = $module.Params.sid $state = $module.Params.state $checkMode = $module.CheckMode @@ -94,12 +98,14 @@ try { $setLoginSplat.add("PasswordMustChange", $true) } } - if ($null -ne $secPassword) { + if (($null -ne $secPassword) -and ($skip_password_reset -eq $false)) { $setLoginSplat.add("SecurePassword", $secPassword) + $changed = $true } # Login already exists if ($null -ne $existingLogin) { + # Splat login status if ($enabled -eq $false) { $disabled = $true $setLoginSplat.add("Disable", $true) @@ -109,7 +115,7 @@ try { $setLoginSplat.add("Enable", $true) } # Login needs to be modified - if (($changed -eq $true) -or ($disabled -ne $existingLogin.IsDisabled) -or ($secPassword)) { + if (($changed -eq $true) -or ($disabled -ne $existingLogin.IsDisabled) -or ($setLoginSplat.ContainsKey("SecurePassword"))) { $output = Set-DbaLogin @setLoginSplat $module.result.changed = $true } @@ -122,6 +128,9 @@ try { if ($enabled -eq $false) { $setLoginSplat.add("Disabled", $true) } + if ($null -ne $sid) { + $setLoginSplat.add("Sid", $sid) + } $output = New-DbaLogin @setLoginSplat $module.result.changed = $true } diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/login.py b/ansible_collections/lowlydba/sqlserver/plugins/modules/login.py index a570d8cfe..5dfdd467f 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/login.py +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/login.py @@ -55,6 +55,19 @@ options: - Enforces password expiration policy. Requires I(password_policy_enforced=true). type: bool required: false + sid: + description: + - Provide an explicit Sid that should be used when creating the account. + type: str + required: false + version_added: '2.1.0' + skip_password_reset: + description: + - Skips the password reset if the login exists and I(password) is set. + type: bool + required: false + default: false + version_added: '2.3.0' author: "John McCall (@lowlydba)" notes: - Module will always return changed if a password is supplied. diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/maintenance_solution.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/maintenance_solution.ps1 index 48f9c90ab..6f94fb400 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/maintenance_solution.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/maintenance_solution.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/memory.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/memory.ps1 index 1b6d2bed9..3b917ccc4 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/memory.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/memory.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/nonquery.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/nonquery.ps1 index fdc34d170..c1180a8d3 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/nonquery.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/nonquery.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/resource_governor.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/resource_governor.ps1 index aa0ade5ed..46b85e59b 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/resource_governor.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/resource_governor.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/restore.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/restore.ps1 index 73c9690fa..57d352b5b 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/restore.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/restore.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/rg_resource_pool.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/rg_resource_pool.ps1 index a6b7ff9b0..22838e177 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/rg_resource_pool.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/rg_resource_pool.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/rg_workload_group.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/rg_workload_group.ps1 index 0b225fd18..f28bb2097 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/rg_workload_group.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/rg_workload_group.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/sa.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/sa.ps1 index 38042bc68..4b2cbefae 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/sa.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/sa.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/sa.py b/ansible_collections/lowlydba/sqlserver/plugins/modules/sa.py index 6aa45fe36..3406fa295 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/sa.py +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/sa.py @@ -58,7 +58,7 @@ EXAMPLES = r''' - name: Disable sa login lowlydba.sqlserver.sa: sql_instance: sql-01.myco.io - disable: true + enabled: false - name: Rename sa login lowlydba.sqlserver.sa: diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/sp_configure.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/sp_configure.ps1 index f4ac80fdc..4351d96d9 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/sp_configure.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/sp_configure.ps1 @@ -7,7 +7,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/sp_whoisactive.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/sp_whoisactive.ps1 index 45fc5ebdd..ba3f59f48 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/sp_whoisactive.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/sp_whoisactive.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/spn.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/spn.ps1 index 12c953bcc..2b8543b05 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/spn.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/spn.ps1 @@ -7,7 +7,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" @@ -32,7 +32,7 @@ if ($null -ne $module.Params.computer_username) { $computer = $module.Params.computer $serviceAccount = $module.Params.service_account $serviceClass = "MSSQLSvc" -$spn = "$serviceClass\$computer" +$spn = "$serviceClass/$computer" $state = $module.Params.state $checkMode = $module.CheckMode $module.Result.changed = $false diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/tcp_port.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/tcp_port.ps1 index bff87bd9a..3bba18424 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/tcp_port.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/tcp_port.ps1 @@ -7,7 +7,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/traceflag.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/traceflag.ps1 index 9e0a1434c..57da0e761 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/traceflag.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/traceflag.ps1 @@ -7,7 +7,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" diff --git a/ansible_collections/lowlydba/sqlserver/plugins/modules/user.ps1 b/ansible_collections/lowlydba/sqlserver/plugins/modules/user.ps1 index 29bbd69b4..4137559e7 100644 --- a/ansible_collections/lowlydba/sqlserver/plugins/modules/user.ps1 +++ b/ansible_collections/lowlydba/sqlserver/plugins/modules/user.ps1 @@ -6,7 +6,7 @@ #AnsibleRequires -CSharpUtil Ansible.Basic #AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils -#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="1.1.112" } +#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" } $ErrorActionPreference = "Stop" @@ -110,6 +110,7 @@ elseif ($state -eq "present") { Login = $login Database = $database DefaultSchema = $defaultSchema + IncludeSystem = $true EnableException = $true WhatIf = $checkMode Force = $true diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/agent_job_schedule/tasks/main.yml b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/agent_job_schedule/tasks/main.yml index 5bd266548..8f0e367ad 100644 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/agent_job_schedule/tasks/main.yml +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/agent_job_schedule/tasks/main.yml @@ -26,7 +26,6 @@ sql_password: "{{ sqlserver_password }}" start_date: "{{ start_date }}" start_time: "{{ start_time }}" - end_date: "{{ end_date }}" end_time: "{{ end_time }}" frequency_type: "{{ frequency_type }}" frequency_interval: "{{ frequency_interval }}" @@ -44,8 +43,9 @@ - assert: that: - result is changed + - result.data.Name == "{{ job_name }}" - - name: Create job schedule with force + - name: Create job schedule with force, no end date lowlydba.sqlserver.agent_job_schedule: schedule: "{{ forced_schedule_name }}" force: true @@ -55,7 +55,7 @@ that: - result.data.ScheduleUid != None - result.data.ActiveStartDate == "3020-05-25T00:00:00.0000000" - - result.data.ActiveEndDate == "3020-05-25T00:00:00.0000000" + - result.data.ActiveEndDate == "9999-12-31T00:00:00.0000000" - result.data.JobCount == 1 - result.data.IsEnabled is true - result.data.ScheduleName == "{{ forced_schedule_name }}" diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/login/tasks/main.yml b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/login/tasks/main.yml index da938fc53..da9b60254 100644 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/login/tasks/main.yml +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/login/tasks/main.yml @@ -6,6 +6,7 @@ password_expiration_enabled: false password_policy_enforced: false password_must_change: false + sid: "0x918315B409D64E4BABB31DF2D9FEA879" enabled: false default_database: "master" language: "us_english" @@ -19,6 +20,7 @@ password: "{{ plain_password }}" password_expiration_enabled: "{{ password_expiration_enabled }}" password_must_change: "{{ password_must_change }}" + sid: "{{ sid }}" enabled: "{{ enabled }}" language: "{{ language }}" state: present @@ -47,6 +49,17 @@ - result.data.Name == "{{ login_name }}" - result.data.DefaultDatabase == "model" + - name: Skip pwd reset + lowlydba.sqlserver.login: + default_database: "model" + password: "ItWasA11ADream!" + skip_password_reset: true + enabled: true + register: result + - assert: + that: + - result is not changed + - name: Drop login lowlydba.sqlserver.login: state: "absent" diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver/tasks/main.yml b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver/tasks/main.yml index 28c3c1cd7..d01023640 100644 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver/tasks/main.yml +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver/tasks/main.yml @@ -3,7 +3,6 @@ when: not sqlserver_windows ansible.builtin.command: > pwsh -Command "{{ item }}" - no_log: "{{ ansible_verbosity | int < 3 }}" loop: - - "{{ dbatools_install_cmd }}" - "{{ dbops_install_cmd }}" + - "{{ dbatools_install_cmd }}" diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver/vars/main.yml b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver/vars/main.yml index 3f8503300..bece0f6fb 100644 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver/vars/main.yml +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver/vars/main.yml @@ -1,12 +1,13 @@ --- -dbatools_min_version: 1.1.112 +dbatools_min_version: 2.0.0 dbatools_install_cmd: > if (-not(Get-Module -FullyQualifiedName @{ModuleName='dbatools';ModuleVersion='{{ dbatools_min_version }}'} -ListAvailable)) { - Install-Module dbatools -MinimumVersion {{ dbatools_min_version }} -Force + Install-Module dbatools -MinimumVersion {{ dbatools_min_version }} -Force -SkipPublisherCheck -AllowClobber + Set-DbatoolsInsecureConnection -Scope FileUserLocal } -dbops_min_version: 0.8.0 +dbops_min_version: 0.9.0 dbops_install_cmd: > if (-not(Get-Module -FullyQualifiedName @{ModuleName='dbops';ModuleVersion='{{ dbops_min_version }}'} -ListAvailable)) { - Install-Module dbops -MinimumVersion {{ dbops_min_version }} -Force + Install-Module dbops -MinimumVersion {{ dbops_min_version }} -Force -SkipPublisherCheck -AllowClobber } diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/connection_plugins/local_pwsh.py b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/connection_plugins/local_pwsh.py index 18ec57fd3..138eb1ec6 100644 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/connection_plugins/local_pwsh.py +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/connection_plugins/local_pwsh.py @@ -26,7 +26,6 @@ import subprocess import fcntl import getpass -import ansible.constants as C from ansible.errors import AnsibleError, AnsibleFileNotFound from ansible.module_utils.compat import selectors from ansible.module_utils.six import text_type, binary_type diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.Basic.cs b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.Basic.cs deleted file mode 100644 index 484f75751..000000000 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.Basic.cs +++ /dev/null @@ -1,1481 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Management.Automation; -using System.Management.Automation.Runspaces; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Security.AccessControl; -using System.Security.Principal; -#if CORECLR -using Newtonsoft.Json; -#else -using System.Web.Script.Serialization; -#endif - -// System.Diagnostics.EventLog.dll reference different versioned dlls that are -// loaded in PSCore, ignore CS1702 so the code will ignore this warning -//NoWarn -Name CS1702 -CLR Core - -//AssemblyReference -Type Newtonsoft.Json.JsonConvert -CLR Core -//AssemblyReference -Type System.Diagnostics.EventLog -CLR Core -//AssemblyReference -Type System.Security.AccessControl.NativeObjectSecurity -CLR Core -//AssemblyReference -Type System.Security.AccessControl.DirectorySecurity -CLR Core -//AssemblyReference -Type System.Security.Principal.IdentityReference -CLR Core - -//AssemblyReference -Name System.Web.Extensions.dll -CLR Framework - -namespace Ansible.Basic -{ - public class AnsibleModule - { - public delegate void ExitHandler(int rc); - public static ExitHandler Exit = new ExitHandler(ExitModule); - - public delegate void WriteLineHandler(string line); - public static WriteLineHandler WriteLine = new WriteLineHandler(WriteLineModule); - - public static bool _DebugArgSpec = false; - - private static List BOOLEANS_TRUE = new List() { "y", "yes", "on", "1", "true", "t", "1.0" }; - private static List BOOLEANS_FALSE = new List() { "n", "no", "off", "0", "false", "f", "0.0" }; - - private string remoteTmp = Path.GetTempPath(); - private string tmpdir = null; - private HashSet noLogValues = new HashSet(); - private List optionsContext = new List(); - private List warnings = new List(); - private List> deprecations = new List>(); - private List cleanupFiles = new List(); - - private Dictionary passVars = new Dictionary() - { - // null values means no mapping, not used in Ansible.Basic.AnsibleModule - { "check_mode", "CheckMode" }, - { "debug", "DebugMode" }, - { "diff", "DiffMode" }, - { "keep_remote_files", "KeepRemoteFiles" }, - { "module_name", "ModuleName" }, - { "no_log", "NoLog" }, - { "remote_tmp", "remoteTmp" }, - { "selinux_special_fs", null }, - { "shell_executable", null }, - { "socket", null }, - { "string_conversion_action", null }, - { "syslog_facility", null }, - { "tmpdir", "tmpdir" }, - { "verbosity", "Verbosity" }, - { "version", "AnsibleVersion" }, - }; - private List passBools = new List() { "check_mode", "debug", "diff", "keep_remote_files", "no_log" }; - private List passInts = new List() { "verbosity" }; - private Dictionary> specDefaults = new Dictionary>() - { - // key - (default, type) - null is freeform - { "apply_defaults", new List() { false, typeof(bool) } }, - { "aliases", new List() { typeof(List), typeof(List) } }, - { "choices", new List() { typeof(List), typeof(List) } }, - { "default", new List() { null, null } }, - { "deprecated_aliases", new List() { typeof(List), typeof(List) } }, - { "elements", new List() { null, null } }, - { "mutually_exclusive", new List() { typeof(List>), typeof(List) } }, - { "no_log", new List() { false, typeof(bool) } }, - { "options", new List() { typeof(Hashtable), typeof(Hashtable) } }, - { "removed_in_version", new List() { null, typeof(string) } }, - { "removed_at_date", new List() { null, typeof(DateTime) } }, - { "removed_from_collection", new List() { null, typeof(string) } }, - { "required", new List() { false, typeof(bool) } }, - { "required_by", new List() { typeof(Hashtable), typeof(Hashtable) } }, - { "required_if", new List() { typeof(List>), typeof(List) } }, - { "required_one_of", new List() { typeof(List>), typeof(List) } }, - { "required_together", new List() { typeof(List>), typeof(List) } }, - { "supports_check_mode", new List() { false, typeof(bool) } }, - { "type", new List() { "str", null } }, - }; - private Dictionary optionTypes = new Dictionary() - { - { "bool", new Func(ParseBool) }, - { "dict", new Func>(ParseDict) }, - { "float", new Func(ParseFloat) }, - { "int", new Func(ParseInt) }, - { "json", new Func(ParseJson) }, - { "list", new Func>(ParseList) }, - { "path", new Func(ParsePath) }, - { "raw", new Func(ParseRaw) }, - { "sid", new Func(ParseSid) }, - { "str", new Func(ParseStr) }, - }; - - public Dictionary Diff = new Dictionary(); - public IDictionary Params = null; - public Dictionary Result = new Dictionary() { { "changed", false } }; - - public bool CheckMode { get; private set; } - public bool DebugMode { get; private set; } - public bool DiffMode { get; private set; } - public bool KeepRemoteFiles { get; private set; } - public string ModuleName { get; private set; } - public bool NoLog { get; private set; } - public int Verbosity { get; private set; } - public string AnsibleVersion { get; private set; } - - public string Tmpdir - { - get - { - if (tmpdir == null) - { - SecurityIdentifier user = WindowsIdentity.GetCurrent().User; - DirectorySecurity dirSecurity = new DirectorySecurity(); - dirSecurity.SetOwner(user); - dirSecurity.SetAccessRuleProtection(true, false); // disable inheritance rules - FileSystemAccessRule ace = new FileSystemAccessRule(user, FileSystemRights.FullControl, - InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, - PropagationFlags.None, AccessControlType.Allow); - dirSecurity.AddAccessRule(ace); - - string baseDir = Path.GetFullPath(Environment.ExpandEnvironmentVariables(remoteTmp)); - if (!Directory.Exists(baseDir)) - { - string failedMsg = null; - try - { -#if CORECLR - DirectoryInfo createdDir = Directory.CreateDirectory(baseDir); - FileSystemAclExtensions.SetAccessControl(createdDir, dirSecurity); -#else - Directory.CreateDirectory(baseDir, dirSecurity); -#endif - } - catch (Exception e) - { - failedMsg = String.Format("Failed to create base tmpdir '{0}': {1}", baseDir, e.Message); - } - - if (failedMsg != null) - { - string envTmp = Path.GetTempPath(); - Warn(String.Format("Unable to use '{0}' as temporary directory, falling back to system tmp '{1}': {2}", baseDir, envTmp, failedMsg)); - baseDir = envTmp; - } - else - { - NTAccount currentUser = (NTAccount)user.Translate(typeof(NTAccount)); - string warnMsg = String.Format("Module remote_tmp {0} did not exist and was created with FullControl to {1}, ", baseDir, currentUser.ToString()); - warnMsg += "this may cause issues when running as another user. To avoid this, create the remote_tmp dir with the correct permissions manually"; - Warn(warnMsg); - } - } - - string dateTime = DateTime.Now.ToFileTime().ToString(); - string dirName = String.Format("ansible-moduletmp-{0}-{1}", dateTime, new Random().Next(0, int.MaxValue)); - string newTmpdir = Path.Combine(baseDir, dirName); -#if CORECLR - DirectoryInfo tmpdirInfo = Directory.CreateDirectory(newTmpdir); - FileSystemAclExtensions.SetAccessControl(tmpdirInfo, dirSecurity); -#else - Directory.CreateDirectory(newTmpdir, dirSecurity); -#endif - tmpdir = newTmpdir; - - if (!KeepRemoteFiles) - cleanupFiles.Add(tmpdir); - } - return tmpdir; - } - } - - public AnsibleModule(string[] args, IDictionary argumentSpec, IDictionary[] fragments = null) - { - // NoLog is not set yet, we cannot rely on FailJson to sanitize the output - // Do the minimum amount to get this running before we actually parse the params - Dictionary aliases = new Dictionary(); - try - { - ValidateArgumentSpec(argumentSpec); - - // Merge the fragments if present into the main arg spec. - if (fragments != null) - { - foreach (IDictionary fragment in fragments) - { - ValidateArgumentSpec(fragment); - MergeFragmentSpec(argumentSpec, fragment); - } - } - - // Used by ansible-test to retrieve the module argument spec, not designed for public use. - if (_DebugArgSpec) - { - // Cannot call exit here because it will be caught with the catch (Exception e) below. Instead - // just throw a new exception with a specific message and the exception block will handle it. - ScriptBlock.Create("Set-Variable -Name ansibleTestArgSpec -Value $args[0] -Scope Global" - ).Invoke(argumentSpec); - throw new Exception("ansible-test validate-modules check"); - } - - // Now make sure all the metadata keys are set to their defaults, this must be done after we've - // potentially output the arg spec for ansible-test. - SetArgumentSpecDefaults(argumentSpec); - - Params = GetParams(args); - aliases = GetAliases(argumentSpec, Params); - SetNoLogValues(argumentSpec, Params); - } - catch (Exception e) - { - if (e.Message == "ansible-test validate-modules check") - Exit(0); - - Dictionary result = new Dictionary - { - { "failed", true }, - { "msg", String.Format("internal error: {0}", e.Message) }, - { "exception", e.ToString() } - }; - WriteLine(ToJson(result)); - Exit(1); - } - - // Initialise public properties to the defaults before we parse the actual inputs - CheckMode = false; - DebugMode = false; - DiffMode = false; - KeepRemoteFiles = false; - ModuleName = "undefined win module"; - NoLog = (bool)argumentSpec["no_log"]; - Verbosity = 0; - AppDomain.CurrentDomain.ProcessExit += CleanupFiles; - - List legalInputs = passVars.Keys.Select(v => "_ansible_" + v).ToList(); - legalInputs.AddRange(((IDictionary)argumentSpec["options"]).Keys.Cast().ToList()); - legalInputs.AddRange(aliases.Keys.Cast().ToList()); - CheckArguments(argumentSpec, Params, legalInputs); - - // Set a Ansible friendly invocation value in the result object - Dictionary invocation = new Dictionary() { { "module_args", Params } }; - Result["invocation"] = RemoveNoLogValues(invocation, noLogValues); - - if (!NoLog) - LogEvent(String.Format("Invoked with:\r\n {0}", FormatLogData(Params, 2)), sanitise: false); - } - - public static AnsibleModule Create(string[] args, IDictionary argumentSpec, IDictionary[] fragments = null) - { - return new AnsibleModule(args, argumentSpec, fragments); - } - - public void Debug(string message) - { - if (DebugMode) - LogEvent(String.Format("[DEBUG] {0}", message)); - } - - public void Deprecate(string message, string version) - { - Deprecate(message, version, null); - } - - public void Deprecate(string message, string version, string collectionName) - { - deprecations.Add(new Dictionary() { - { "msg", message }, { "version", version }, { "collection_name", collectionName } }); - LogEvent(String.Format("[DEPRECATION WARNING] {0} {1}", message, version)); - } - - public void Deprecate(string message, DateTime date) - { - Deprecate(message, date, null); - } - - public void Deprecate(string message, DateTime date, string collectionName) - { - string isoDate = date.ToString("yyyy-MM-dd"); - deprecations.Add(new Dictionary() { - { "msg", message }, { "date", isoDate }, { "collection_name", collectionName } }); - LogEvent(String.Format("[DEPRECATION WARNING] {0} {1}", message, isoDate)); - } - - public void ExitJson() - { - WriteLine(GetFormattedResults(Result)); - CleanupFiles(null, null); - Exit(0); - } - - public void FailJson(string message) { FailJson(message, null, null); } - public void FailJson(string message, ErrorRecord psErrorRecord) { FailJson(message, psErrorRecord, null); } - public void FailJson(string message, Exception exception) { FailJson(message, null, exception); } - private void FailJson(string message, ErrorRecord psErrorRecord, Exception exception) - { - Result["failed"] = true; - Result["msg"] = RemoveNoLogValues(message, noLogValues); - - - if (!Result.ContainsKey("exception") && (Verbosity > 2 || DebugMode)) - { - if (psErrorRecord != null) - { - string traceback = String.Format("{0}\r\n{1}", psErrorRecord.ToString(), psErrorRecord.InvocationInfo.PositionMessage); - traceback += String.Format("\r\n + CategoryInfo : {0}", psErrorRecord.CategoryInfo.ToString()); - traceback += String.Format("\r\n + FullyQualifiedErrorId : {0}", psErrorRecord.FullyQualifiedErrorId.ToString()); - traceback += String.Format("\r\n\r\nScriptStackTrace:\r\n{0}", psErrorRecord.ScriptStackTrace); - Result["exception"] = traceback; - } - else if (exception != null) - Result["exception"] = exception.ToString(); - } - - WriteLine(GetFormattedResults(Result)); - CleanupFiles(null, null); - Exit(1); - } - - public void LogEvent(string message, EventLogEntryType logEntryType = EventLogEntryType.Information, bool sanitise = true) - { - // non-Windows hack; event log is not supported, not implementing a x-plat compat logger at this time - // original content left as comment, because it may make it easier to update this - return; - /* - if (NoLog) - return; - - string logSource = "Ansible"; - bool logSourceExists = false; - try - { - logSourceExists = EventLog.SourceExists(logSource); - } - catch (System.Security.SecurityException) { } // non admin users may not have permission - - if (!logSourceExists) - { - try - { - EventLog.CreateEventSource(logSource, "Application"); - } - catch (System.Security.SecurityException) - { - // Cannot call Warn as that calls LogEvent and we get stuck in a loop - warnings.Add(String.Format("Access error when creating EventLog source {0}, logging to the Application source instead", logSource)); - logSource = "Application"; - } - } - if (sanitise) - message = (string)RemoveNoLogValues(message, noLogValues); - message = String.Format("{0} - {1}", ModuleName, message); - - using (EventLog eventLog = new EventLog("Application")) - { - eventLog.Source = logSource; - try - { - eventLog.WriteEntry(message, logEntryType, 0); - } - catch (System.InvalidOperationException) { } // Ignore permission errors on the Application event log - catch (System.Exception e) - { - // Cannot call Warn as that calls LogEvent and we get stuck in a loop - warnings.Add(String.Format("Unknown error when creating event log entry: {0}", e.Message)); - } - } - */ - } - - public void Warn(string message) - { - warnings.Add(message); - LogEvent(String.Format("[WARNING] {0}", message), EventLogEntryType.Warning); - } - - public static object FromJson(string json) { return FromJson(json); } - public static T FromJson(string json) - { -#if CORECLR - return JsonConvert.DeserializeObject(json); -#else - JavaScriptSerializer jss = new JavaScriptSerializer(); - jss.MaxJsonLength = int.MaxValue; - jss.RecursionLimit = int.MaxValue; - return jss.Deserialize(json); -#endif - } - - public static string ToJson(object obj) - { - // Using PowerShell to serialize the JSON is preferable over the native .NET libraries as it handles - // PS Objects a lot better than the alternatives. In case we are debugging in Visual Studio we have a - // fallback to the other libraries as we won't be dealing with PowerShell objects there. - if (Runspace.DefaultRunspace != null) - { - PSObject rawOut = ScriptBlock.Create("ConvertTo-Json -InputObject $args[0] -Depth 99 -Compress").Invoke(obj)[0]; - return rawOut.BaseObject as string; - } - else - { -#if CORECLR - return JsonConvert.SerializeObject(obj); -#else - JavaScriptSerializer jss = new JavaScriptSerializer(); - jss.MaxJsonLength = int.MaxValue; - jss.RecursionLimit = int.MaxValue; - return jss.Serialize(obj); -#endif - } - } - - public static IDictionary GetParams(string[] args) - { - if (args.Length > 0) - { - string inputJson = File.ReadAllText(args[0]); - Dictionary rawParams = FromJson>(inputJson); - if (!rawParams.ContainsKey("ANSIBLE_MODULE_ARGS")) - throw new ArgumentException("Module was unable to get ANSIBLE_MODULE_ARGS value from the argument path json"); - return (IDictionary)rawParams["ANSIBLE_MODULE_ARGS"]; - } - else - { - // $complex_args is already a Hashtable, no need to waste time converting to a dictionary - PSObject rawArgs = ScriptBlock.Create("$complex_args").Invoke()[0]; - return rawArgs.BaseObject as Hashtable; - } - } - - public static bool ParseBool(object value) - { - if (value.GetType() == typeof(bool)) - return (bool)value; - - List booleans = new List(); - booleans.AddRange(BOOLEANS_TRUE); - booleans.AddRange(BOOLEANS_FALSE); - - string stringValue = ParseStr(value).ToLowerInvariant().Trim(); - if (BOOLEANS_TRUE.Contains(stringValue)) - return true; - else if (BOOLEANS_FALSE.Contains(stringValue)) - return false; - - string msg = String.Format("The value '{0}' is not a valid boolean. Valid booleans include: {1}", - stringValue, String.Join(", ", booleans)); - throw new ArgumentException(msg); - } - - public static Dictionary ParseDict(object value) - { - Type valueType = value.GetType(); - if (valueType == typeof(Dictionary)) - return (Dictionary)value; - else if (value is IDictionary) - return ((IDictionary)value).Cast().ToDictionary(kvp => (string)kvp.Key, kvp => kvp.Value); - else if (valueType == typeof(string)) - { - string stringValue = (string)value; - if (stringValue.StartsWith("{") && stringValue.EndsWith("}")) - return FromJson>((string)value); - else if (stringValue.IndexOfAny(new char[1] { '=' }) != -1) - { - List fields = new List(); - List fieldBuffer = new List(); - char? inQuote = null; - bool inEscape = false; - string field; - - foreach (char c in stringValue.ToCharArray()) - { - if (inEscape) - { - fieldBuffer.Add(c); - inEscape = false; - } - else if (c == '\\') - inEscape = true; - else if (inQuote == null && (c == '\'' || c == '"')) - inQuote = c; - else if (inQuote != null && c == inQuote) - inQuote = null; - else if (inQuote == null && (c == ',' || c == ' ')) - { - field = String.Join("", fieldBuffer); - if (field != "") - fields.Add(field); - fieldBuffer = new List(); - } - else - fieldBuffer.Add(c); - } - - field = String.Join("", fieldBuffer); - if (field != "") - fields.Add(field); - - return fields.Distinct().Select(i => i.Split(new[] { '=' }, 2)).ToDictionary(i => i[0], i => i.Length > 1 ? (object)i[1] : null); - } - else - throw new ArgumentException("string cannot be converted to a dict, must either be a JSON string or in the key=value form"); - } - - throw new ArgumentException(String.Format("{0} cannot be converted to a dict", valueType.FullName)); - } - - public static float ParseFloat(object value) - { - if (value.GetType() == typeof(float)) - return (float)value; - - string valueStr = ParseStr(value); - return float.Parse(valueStr); - } - - public static int ParseInt(object value) - { - Type valueType = value.GetType(); - if (valueType == typeof(int)) - return (int)value; - else - return Int32.Parse(ParseStr(value)); - } - - public static string ParseJson(object value) - { - // mostly used to ensure a dict is a json string as it may - // have been converted on the controller side - Type valueType = value.GetType(); - if (value is IDictionary) - return ToJson(value); - else if (valueType == typeof(string)) - return (string)value; - else - throw new ArgumentException(String.Format("{0} cannot be converted to json", valueType.FullName)); - } - - public static List ParseList(object value) - { - if (value == null) - return null; - - Type valueType = value.GetType(); - if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) - return (List)value; - else if (valueType == typeof(ArrayList)) - return ((ArrayList)value).Cast().ToList(); - else if (valueType.IsArray) - return ((object[])value).ToList(); - else if (valueType == typeof(string)) - return ((string)value).Split(',').Select(s => s.Trim()).ToList(); - else if (valueType == typeof(int)) - return new List() { value }; - else - throw new ArgumentException(String.Format("{0} cannot be converted to a list", valueType.FullName)); - } - - public static string ParsePath(object value) - { - string stringValue = ParseStr(value); - - // do not validate, expand the env vars if it starts with \\?\ as - // it is a special path designed for the NT kernel to interpret - if (stringValue.StartsWith(@"\\?\")) - return stringValue; - - stringValue = Environment.ExpandEnvironmentVariables(stringValue); - if (stringValue.IndexOfAny(Path.GetInvalidPathChars()) != -1) - throw new ArgumentException("string value contains invalid path characters, cannot convert to path"); - - // will fire an exception if it contains any invalid chars - Path.GetFullPath(stringValue); - return stringValue; - } - - public static object ParseRaw(object value) { return value; } - - public static SecurityIdentifier ParseSid(object value) - { - string stringValue = ParseStr(value); - - try - { - return new SecurityIdentifier(stringValue); - } - catch (ArgumentException) { } // ignore failures string may not have been a SID - - NTAccount account = new NTAccount(stringValue); - return (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier)); - } - - public static string ParseStr(object value) { return value.ToString(); } - - private void ValidateArgumentSpec(IDictionary argumentSpec) - { - Dictionary changedValues = new Dictionary(); - foreach (DictionaryEntry entry in argumentSpec) - { - string key = (string)entry.Key; - - // validate the key is a valid argument spec key - if (!specDefaults.ContainsKey(key)) - { - string msg = String.Format("argument spec entry contains an invalid key '{0}', valid keys: {1}", - key, String.Join(", ", specDefaults.Keys)); - throw new ArgumentException(FormatOptionsContext(msg, " - ")); - } - - // ensure the value is casted to the type we expect - Type optionType = null; - if (entry.Value != null) - optionType = (Type)specDefaults[key][1]; - if (optionType != null) - { - Type actualType = entry.Value.GetType(); - bool invalid = false; - if (optionType.IsGenericType && optionType.GetGenericTypeDefinition() == typeof(List<>)) - { - // verify the actual type is not just a single value of the list type - Type entryType = optionType.GetGenericArguments()[0]; - object[] arrayElementTypes = new object[] - { - null, // ArrayList does not have an ElementType - entryType, - typeof(object), // Hope the object is actually entryType or it can at least be casted. - }; - - bool isArray = entry.Value is IList && arrayElementTypes.Contains(actualType.GetElementType()); - if (actualType == entryType || isArray) - { - object rawArray; - if (isArray) - rawArray = entry.Value; - else - rawArray = new object[1] { entry.Value }; - - MethodInfo castMethod = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(entryType); - MethodInfo toListMethod = typeof(Enumerable).GetMethod("ToList").MakeGenericMethod(entryType); - - var enumerable = castMethod.Invoke(null, new object[1] { rawArray }); - var newList = toListMethod.Invoke(null, new object[1] { enumerable }); - changedValues.Add(key, newList); - } - else if (actualType != optionType && !(actualType == typeof(List))) - invalid = true; - } - else - invalid = actualType != optionType; - - if (invalid) - { - string msg = String.Format("argument spec for '{0}' did not match expected type {1}: actual type {2}", - key, optionType.FullName, actualType.FullName); - throw new ArgumentException(FormatOptionsContext(msg, " - ")); - } - } - - // recursively validate the spec - if (key == "options" && entry.Value != null) - { - IDictionary optionsSpec = (IDictionary)entry.Value; - foreach (DictionaryEntry optionEntry in optionsSpec) - { - optionsContext.Add((string)optionEntry.Key); - IDictionary optionMeta = (IDictionary)optionEntry.Value; - ValidateArgumentSpec(optionMeta); - optionsContext.RemoveAt(optionsContext.Count - 1); - } - } - - // validate the type and elements key type values are known types - if (key == "type" || key == "elements" && entry.Value != null) - { - Type valueType = entry.Value.GetType(); - if (valueType == typeof(string)) - { - string typeValue = (string)entry.Value; - if (!optionTypes.ContainsKey(typeValue)) - { - string msg = String.Format("{0} '{1}' is unsupported", key, typeValue); - msg = String.Format("{0}. Valid types are: {1}", FormatOptionsContext(msg, " - "), String.Join(", ", optionTypes.Keys)); - throw new ArgumentException(msg); - } - } - else if (!(entry.Value is Delegate)) - { - string msg = String.Format("{0} must either be a string or delegate, was: {1}", key, valueType.FullName); - throw new ArgumentException(FormatOptionsContext(msg, " - ")); - } - } - } - - // Outside of the spec iterator, change the values that were casted above - foreach (KeyValuePair changedValue in changedValues) - argumentSpec[changedValue.Key] = changedValue.Value; - } - - private void MergeFragmentSpec(IDictionary argumentSpec, IDictionary fragment) - { - foreach (DictionaryEntry fragmentEntry in fragment) - { - string fragmentKey = fragmentEntry.Key.ToString(); - - if (argumentSpec.Contains(fragmentKey)) - { - // We only want to add new list entries and merge dictionary new keys and values. Leave the other - // values as is in the argument spec as that takes priority over the fragment. - if (fragmentEntry.Value is IDictionary) - { - MergeFragmentSpec((IDictionary)argumentSpec[fragmentKey], (IDictionary)fragmentEntry.Value); - } - else if (fragmentEntry.Value is IList) - { - IList specValue = (IList)argumentSpec[fragmentKey]; - foreach (object fragmentValue in (IList)fragmentEntry.Value) - specValue.Add(fragmentValue); - } - } - else - argumentSpec[fragmentKey] = fragmentEntry.Value; - } - } - - private void SetArgumentSpecDefaults(IDictionary argumentSpec) - { - foreach (KeyValuePair> metadataEntry in specDefaults) - { - List defaults = metadataEntry.Value; - object defaultValue = defaults[0]; - if (defaultValue != null && defaultValue.GetType() == typeof(Type).GetType()) - defaultValue = Activator.CreateInstance((Type)defaultValue); - - if (!argumentSpec.Contains(metadataEntry.Key)) - argumentSpec[metadataEntry.Key] = defaultValue; - } - - // Recursively set the defaults for any inner options. - foreach (DictionaryEntry entry in argumentSpec) - { - if (entry.Value == null || entry.Key.ToString() != "options") - continue; - - IDictionary optionsSpec = (IDictionary)entry.Value; - foreach (DictionaryEntry optionEntry in optionsSpec) - { - optionsContext.Add((string)optionEntry.Key); - IDictionary optionMeta = (IDictionary)optionEntry.Value; - SetArgumentSpecDefaults(optionMeta); - optionsContext.RemoveAt(optionsContext.Count - 1); - } - } - } - - private Dictionary GetAliases(IDictionary argumentSpec, IDictionary parameters) - { - Dictionary aliasResults = new Dictionary(); - - foreach (DictionaryEntry entry in (IDictionary)argumentSpec["options"]) - { - string k = (string)entry.Key; - Hashtable v = (Hashtable)entry.Value; - - List aliases = (List)v["aliases"]; - object defaultValue = v["default"]; - bool required = (bool)v["required"]; - - if (defaultValue != null && required) - throw new ArgumentException(String.Format("required and default are mutually exclusive for {0}", k)); - - foreach (string alias in aliases) - { - aliasResults.Add(alias, k); - if (parameters.Contains(alias)) - parameters[k] = parameters[alias]; - } - - List deprecatedAliases = (List)v["deprecated_aliases"]; - foreach (Hashtable depInfo in deprecatedAliases) - { - foreach (string keyName in new List { "name" }) - { - if (!depInfo.ContainsKey(keyName)) - { - string msg = String.Format("{0} is required in a deprecated_aliases entry", keyName); - throw new ArgumentException(FormatOptionsContext(msg, " - ")); - } - } - if (!depInfo.ContainsKey("version") && !depInfo.ContainsKey("date")) - { - string msg = "One of version or date is required in a deprecated_aliases entry"; - throw new ArgumentException(FormatOptionsContext(msg, " - ")); - } - if (depInfo.ContainsKey("version") && depInfo.ContainsKey("date")) - { - string msg = "Only one of version or date is allowed in a deprecated_aliases entry"; - throw new ArgumentException(FormatOptionsContext(msg, " - ")); - } - if (depInfo.ContainsKey("date") && depInfo["date"].GetType() != typeof(DateTime)) - { - string msg = "A deprecated_aliases date must be a DateTime object"; - throw new ArgumentException(FormatOptionsContext(msg, " - ")); - } - string collectionName = null; - if (depInfo.ContainsKey("collection_name")) - { - collectionName = (string)depInfo["collection_name"]; - } - string aliasName = (string)depInfo["name"]; - - if (parameters.Contains(aliasName)) - { - string msg = String.Format("Alias '{0}' is deprecated. See the module docs for more information", aliasName); - if (depInfo.ContainsKey("version")) - { - string depVersion = (string)depInfo["version"]; - Deprecate(FormatOptionsContext(msg, " - "), depVersion, collectionName); - } - if (depInfo.ContainsKey("date")) - { - DateTime depDate = (DateTime)depInfo["date"]; - Deprecate(FormatOptionsContext(msg, " - "), depDate, collectionName); - } - } - } - } - - return aliasResults; - } - - private void SetNoLogValues(IDictionary argumentSpec, IDictionary parameters) - { - foreach (DictionaryEntry entry in (IDictionary)argumentSpec["options"]) - { - string k = (string)entry.Key; - Hashtable v = (Hashtable)entry.Value; - - if ((bool)v["no_log"]) - { - object noLogObject = parameters.Contains(k) ? parameters[k] : null; - string noLogString = noLogObject == null ? "" : noLogObject.ToString(); - if (!String.IsNullOrEmpty(noLogString)) - noLogValues.Add(noLogString); - } - string collectionName = null; - if (v.ContainsKey("removed_from_collection")) - { - collectionName = (string)v["removed_from_collection"]; - } - - object removedInVersion = v["removed_in_version"]; - if (removedInVersion != null && parameters.Contains(k)) - Deprecate(String.Format("Param '{0}' is deprecated. See the module docs for more information", k), - removedInVersion.ToString(), collectionName); - - object removedAtDate = v["removed_at_date"]; - if (removedAtDate != null && parameters.Contains(k)) - Deprecate(String.Format("Param '{0}' is deprecated. See the module docs for more information", k), - (DateTime)removedAtDate, collectionName); - } - } - - private void CheckArguments(IDictionary spec, IDictionary param, List legalInputs) - { - // initially parse the params and check for unsupported ones and set internal vars - CheckUnsupportedArguments(param, legalInputs); - - // Only run this check if we are at the root argument (optionsContext.Count == 0) - if (CheckMode && !(bool)spec["supports_check_mode"] && optionsContext.Count == 0) - { - Result["skipped"] = true; - Result["msg"] = String.Format("remote module ({0}) does not support check mode", ModuleName); - ExitJson(); - } - IDictionary optionSpec = (IDictionary)spec["options"]; - - CheckMutuallyExclusive(param, (IList)spec["mutually_exclusive"]); - CheckRequiredArguments(optionSpec, param); - - // set the parameter types based on the type spec value - foreach (DictionaryEntry entry in optionSpec) - { - string k = (string)entry.Key; - Hashtable v = (Hashtable)entry.Value; - - object value = param.Contains(k) ? param[k] : null; - if (value != null) - { - // convert the current value to the wanted type - Delegate typeConverter; - string type; - if (v["type"].GetType() == typeof(string)) - { - type = (string)v["type"]; - typeConverter = optionTypes[type]; - } - else - { - type = "delegate"; - typeConverter = (Delegate)v["type"]; - } - - try - { - value = typeConverter.DynamicInvoke(value); - param[k] = value; - } - catch (Exception e) - { - string msg = String.Format("argument for {0} is of type {1} and we were unable to convert to {2}: {3}", - k, value.GetType(), type, e.InnerException.Message); - FailJson(FormatOptionsContext(msg)); - } - - // ensure it matches the choices if there are choices set - List choices = ((List)v["choices"]).Select(x => x.ToString()).Cast().ToList(); - if (choices.Count > 0) - { - List values; - string choiceMsg; - if (type == "list") - { - values = ((List)value).Select(x => x.ToString()).Cast().ToList(); - choiceMsg = "one or more of"; - } - else - { - values = new List() { value.ToString() }; - choiceMsg = "one of"; - } - - List diffList = values.Except(choices, StringComparer.OrdinalIgnoreCase).ToList(); - List caseDiffList = values.Except(choices).ToList(); - if (diffList.Count > 0) - { - string msg = String.Format("value of {0} must be {1}: {2}. Got no match for: {3}", - k, choiceMsg, String.Join(", ", choices), String.Join(", ", diffList)); - FailJson(FormatOptionsContext(msg)); - } - /* - For now we will just silently accept case insensitive choices, uncomment this if we want to add it back in - else if (caseDiffList.Count > 0) - { - // For backwards compatibility with Legacy.psm1 we need to be matching choices that are not case sensitive. - // We will warn the user it was case insensitive and tell them this will become case sensitive in the future. - string msg = String.Format( - "value of {0} was a case insensitive match of {1}: {2}. Checking of choices will be case sensitive in a future Ansible release. Case insensitive matches were: {3}", - k, choiceMsg, String.Join(", ", choices), String.Join(", ", caseDiffList.Select(x => RemoveNoLogValues(x, noLogValues))) - ); - Warn(FormatOptionsContext(msg)); - }*/ - } - } - } - - CheckRequiredTogether(param, (IList)spec["required_together"]); - CheckRequiredOneOf(param, (IList)spec["required_one_of"]); - CheckRequiredIf(param, (IList)spec["required_if"]); - CheckRequiredBy(param, (IDictionary)spec["required_by"]); - - // finally ensure all missing parameters are set to null and handle sub options - foreach (DictionaryEntry entry in optionSpec) - { - string k = (string)entry.Key; - IDictionary v = (IDictionary)entry.Value; - - if (!param.Contains(k)) - param[k] = null; - - CheckSubOption(param, k, v); - } - } - - private void CheckUnsupportedArguments(IDictionary param, List legalInputs) - { - HashSet unsupportedParameters = new HashSet(); - HashSet caseUnsupportedParameters = new HashSet(); - List removedParameters = new List(); - - foreach (DictionaryEntry entry in param) - { - string paramKey = (string)entry.Key; - if (!legalInputs.Contains(paramKey, StringComparer.OrdinalIgnoreCase)) - unsupportedParameters.Add(paramKey); - else if (!legalInputs.Contains(paramKey)) - // For backwards compatibility we do not care about the case but we need to warn the users as this will - // change in a future Ansible release. - caseUnsupportedParameters.Add(paramKey); - else if (paramKey.StartsWith("_ansible_")) - { - removedParameters.Add(paramKey); - string key = paramKey.Replace("_ansible_", ""); - // skip setting NoLog if NoLog is already set to true (set by the module) - // or there's no mapping for this key - if ((key == "no_log" && NoLog == true) || (passVars[key] == null)) - continue; - - object value = entry.Value; - if (passBools.Contains(key)) - value = ParseBool(value); - else if (passInts.Contains(key)) - value = ParseInt(value); - - string propertyName = passVars[key]; - PropertyInfo property = typeof(AnsibleModule).GetProperty(propertyName); - FieldInfo field = typeof(AnsibleModule).GetField(propertyName, BindingFlags.NonPublic | BindingFlags.Instance); - if (property != null) - property.SetValue(this, value, null); - else if (field != null) - field.SetValue(this, value); - else - FailJson(String.Format("implementation error: unknown AnsibleModule property {0}", propertyName)); - } - } - foreach (string parameter in removedParameters) - param.Remove(parameter); - - if (unsupportedParameters.Count > 0) - { - legalInputs.RemoveAll(x => passVars.Keys.Contains(x.Replace("_ansible_", ""))); - string msg = String.Format("Unsupported parameters for ({0}) module: {1}", ModuleName, String.Join(", ", unsupportedParameters)); - msg = String.Format("{0}. Supported parameters include: {1}", FormatOptionsContext(msg), String.Join(", ", legalInputs)); - FailJson(msg); - } - - /* - // Uncomment when we want to start warning users around options that are not a case sensitive match to the spec - if (caseUnsupportedParameters.Count > 0) - { - legalInputs.RemoveAll(x => passVars.Keys.Contains(x.Replace("_ansible_", ""))); - string msg = String.Format("Parameters for ({0}) was a case insensitive match: {1}", ModuleName, String.Join(", ", caseUnsupportedParameters)); - msg = String.Format("{0}. Module options will become case sensitive in a future Ansible release. Supported parameters include: {1}", - FormatOptionsContext(msg), String.Join(", ", legalInputs)); - Warn(msg); - }*/ - - // Make sure we convert all the incorrect case params to the ones set by the module spec - foreach (string key in caseUnsupportedParameters) - { - string correctKey = legalInputs[legalInputs.FindIndex(s => s.Equals(key, StringComparison.OrdinalIgnoreCase))]; - object value = param[key]; - param.Remove(key); - param.Add(correctKey, value); - } - } - - private void CheckMutuallyExclusive(IDictionary param, IList mutuallyExclusive) - { - if (mutuallyExclusive == null) - return; - - foreach (object check in mutuallyExclusive) - { - List mutualCheck = ((IList)check).Cast().ToList(); - int count = 0; - foreach (string entry in mutualCheck) - if (param.Contains(entry)) - count++; - - if (count > 1) - { - string msg = String.Format("parameters are mutually exclusive: {0}", String.Join(", ", mutualCheck)); - FailJson(FormatOptionsContext(msg)); - } - } - } - - private void CheckRequiredArguments(IDictionary spec, IDictionary param) - { - List missing = new List(); - foreach (DictionaryEntry entry in spec) - { - string k = (string)entry.Key; - Hashtable v = (Hashtable)entry.Value; - - // set defaults for values not already set - object defaultValue = v["default"]; - if (defaultValue != null && !param.Contains(k)) - param[k] = defaultValue; - - // check required arguments - bool required = (bool)v["required"]; - if (required && !param.Contains(k)) - missing.Add(k); - } - if (missing.Count > 0) - { - string msg = String.Format("missing required arguments: {0}", String.Join(", ", missing)); - FailJson(FormatOptionsContext(msg)); - } - } - - private void CheckRequiredTogether(IDictionary param, IList requiredTogether) - { - if (requiredTogether == null) - return; - - foreach (object check in requiredTogether) - { - List requiredCheck = ((IList)check).Cast().ToList(); - List found = new List(); - foreach (string field in requiredCheck) - if (param.Contains(field)) - found.Add(true); - else - found.Add(false); - - if (found.Contains(true) && found.Contains(false)) - { - string msg = String.Format("parameters are required together: {0}", String.Join(", ", requiredCheck)); - FailJson(FormatOptionsContext(msg)); - } - } - } - - private void CheckRequiredOneOf(IDictionary param, IList requiredOneOf) - { - if (requiredOneOf == null) - return; - - foreach (object check in requiredOneOf) - { - List requiredCheck = ((IList)check).Cast().ToList(); - int count = 0; - foreach (string field in requiredCheck) - if (param.Contains(field)) - count++; - - if (count == 0) - { - string msg = String.Format("one of the following is required: {0}", String.Join(", ", requiredCheck)); - FailJson(FormatOptionsContext(msg)); - } - } - } - - private void CheckRequiredIf(IDictionary param, IList requiredIf) - { - if (requiredIf == null) - return; - - foreach (object check in requiredIf) - { - IList requiredCheck = (IList)check; - List missing = new List(); - List missingFields = new List(); - int maxMissingCount = 1; - bool oneRequired = false; - - if (requiredCheck.Count < 3 && requiredCheck.Count < 4) - FailJson(String.Format("internal error: invalid required_if value count of {0}, expecting 3 or 4 entries", requiredCheck.Count)); - else if (requiredCheck.Count == 4) - oneRequired = (bool)requiredCheck[3]; - - string key = (string)requiredCheck[0]; - object val = requiredCheck[1]; - IList requirements = (IList)requiredCheck[2]; - - if (ParseStr(param[key]) != ParseStr(val)) - continue; - - string term = "all"; - if (oneRequired) - { - maxMissingCount = requirements.Count; - term = "any"; - } - - foreach (string required in requirements.Cast()) - if (!param.Contains(required)) - missing.Add(required); - - if (missing.Count >= maxMissingCount) - { - string msg = String.Format("{0} is {1} but {2} of the following are missing: {3}", - key, val.ToString(), term, String.Join(", ", missing)); - FailJson(FormatOptionsContext(msg)); - } - } - } - - private void CheckRequiredBy(IDictionary param, IDictionary requiredBy) - { - foreach (DictionaryEntry entry in requiredBy) - { - string key = (string)entry.Key; - if (!param.Contains(key)) - continue; - - List missing = new List(); - List requires = ParseList(entry.Value).Cast().ToList(); - foreach (string required in requires) - if (!param.Contains(required)) - missing.Add(required); - - if (missing.Count > 0) - { - string msg = String.Format("missing parameter(s) required by '{0}': {1}", key, String.Join(", ", missing)); - FailJson(FormatOptionsContext(msg)); - } - } - } - - private void CheckSubOption(IDictionary param, string key, IDictionary spec) - { - object value = param[key]; - - string type; - if (spec["type"].GetType() == typeof(string)) - type = (string)spec["type"]; - else - type = "delegate"; - - string elements = null; - Delegate typeConverter = null; - if (spec["elements"] != null && spec["elements"].GetType() == typeof(string)) - { - elements = (string)spec["elements"]; - typeConverter = optionTypes[elements]; - } - else if (spec["elements"] != null) - { - elements = "delegate"; - typeConverter = (Delegate)spec["elements"]; - } - - if (!(type == "dict" || (type == "list" && elements != null))) - // either not a dict, or list with the elements set, so continue - return; - else if (type == "list") - { - // cast each list element to the type specified - if (value == null) - return; - - List newValue = new List(); - foreach (object element in (List)value) - { - if (elements == "dict") - newValue.Add(ParseSubSpec(spec, element, key)); - else - { - try - { - object newElement = typeConverter.DynamicInvoke(element); - newValue.Add(newElement); - } - catch (Exception e) - { - string msg = String.Format("argument for list entry {0} is of type {1} and we were unable to convert to {2}: {3}", - key, element.GetType(), elements, e.Message); - FailJson(FormatOptionsContext(msg)); - } - } - } - - param[key] = newValue; - } - else - param[key] = ParseSubSpec(spec, value, key); - } - - private object ParseSubSpec(IDictionary spec, object value, string context) - { - bool applyDefaults = (bool)spec["apply_defaults"]; - - // set entry to an empty dict if apply_defaults is set - IDictionary optionsSpec = (IDictionary)spec["options"]; - if (applyDefaults && optionsSpec.Keys.Count > 0 && value == null) - value = new Dictionary(); - else if (optionsSpec.Keys.Count == 0 || value == null) - return value; - - optionsContext.Add(context); - Dictionary newValue = (Dictionary)ParseDict(value); - Dictionary aliases = GetAliases(spec, newValue); - SetNoLogValues(spec, newValue); - - List subLegalInputs = optionsSpec.Keys.Cast().ToList(); - subLegalInputs.AddRange(aliases.Keys.Cast().ToList()); - - CheckArguments(spec, newValue, subLegalInputs); - optionsContext.RemoveAt(optionsContext.Count - 1); - return newValue; - } - - private string GetFormattedResults(Dictionary result) - { - if (!result.ContainsKey("invocation")) - result["invocation"] = new Dictionary() { { "module_args", RemoveNoLogValues(Params, noLogValues) } }; - - if (warnings.Count > 0) - result["warnings"] = warnings; - - if (deprecations.Count > 0) - result["deprecations"] = deprecations; - - if (Diff.Count > 0 && DiffMode) - result["diff"] = Diff; - - return ToJson(result); - } - - private string FormatLogData(object data, int indentLevel) - { - if (data == null) - return "$null"; - - string msg = ""; - if (data is IList) - { - string newMsg = ""; - foreach (object value in (IList)data) - { - string entryValue = FormatLogData(value, indentLevel + 2); - newMsg += String.Format("\r\n{0}- {1}", new String(' ', indentLevel), entryValue); - } - msg += newMsg; - } - else if (data is IDictionary) - { - bool start = true; - foreach (DictionaryEntry entry in (IDictionary)data) - { - string newMsg = FormatLogData(entry.Value, indentLevel + 2); - if (!start) - msg += String.Format("\r\n{0}", new String(' ', indentLevel)); - msg += String.Format("{0}: {1}", (string)entry.Key, newMsg); - start = false; - } - } - else - msg = (string)RemoveNoLogValues(ParseStr(data), noLogValues); - - return msg; - } - - private object RemoveNoLogValues(object value, HashSet noLogStrings) - { - Queue> deferredRemovals = new Queue>(); - object newValue = RemoveValueConditions(value, noLogStrings, deferredRemovals); - - while (deferredRemovals.Count > 0) - { - Tuple data = deferredRemovals.Dequeue(); - object oldData = data.Item1; - object newData = data.Item2; - - if (oldData is IDictionary) - { - foreach (DictionaryEntry entry in (IDictionary)oldData) - { - object newElement = RemoveValueConditions(entry.Value, noLogStrings, deferredRemovals); - ((IDictionary)newData).Add((string)entry.Key, newElement); - } - } - else - { - foreach (object element in (IList)oldData) - { - object newElement = RemoveValueConditions(element, noLogStrings, deferredRemovals); - ((IList)newData).Add(newElement); - } - } - } - - return newValue; - } - - private object RemoveValueConditions(object value, HashSet noLogStrings, Queue> deferredRemovals) - { - if (value == null) - return value; - - Type valueType = value.GetType(); - HashSet numericTypes = new HashSet - { - typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), - typeof(long), typeof(ulong), typeof(decimal), typeof(double), typeof(float) - }; - - if (numericTypes.Contains(valueType) || valueType == typeof(bool)) - { - string valueString = ParseStr(value); - if (noLogStrings.Contains(valueString)) - return "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"; - foreach (string omitMe in noLogStrings) - if (valueString.Contains(omitMe)) - return "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"; - } - else if (valueType == typeof(DateTime)) - value = ((DateTime)value).ToString("o"); - else if (value is IList) - { - List newValue = new List(); - deferredRemovals.Enqueue(new Tuple((IList)value, newValue)); - value = newValue; - } - else if (value is IDictionary) - { - Hashtable newValue = new Hashtable(); - deferredRemovals.Enqueue(new Tuple((IDictionary)value, newValue)); - value = newValue; - } - else - { - string stringValue = value.ToString(); - if (noLogStrings.Contains(stringValue)) - return "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"; - foreach (string omitMe in noLogStrings) - if (stringValue.Contains(omitMe)) - return (stringValue).Replace(omitMe, "********"); - value = stringValue; - } - return value; - } - - private void CleanupFiles(object s, EventArgs ev) - { - foreach (string path in cleanupFiles) - { - if (File.Exists(path)) - File.Delete(path); - else if (Directory.Exists(path)) - Directory.Delete(path, true); - } - cleanupFiles = new List(); - } - - private string FormatOptionsContext(string msg, string prefix = " ") - { - if (optionsContext.Count > 0) - msg += String.Format("{0}found in {1}", prefix, String.Join(" -> ", optionsContext)); - return msg; - } - - [DllImport("kernel32.dll")] - private static extern IntPtr GetConsoleWindow(); - - private static void ExitModule(int rc) - { - // When running in a Runspace Environment.Exit will kill the entire - // process which is not what we want, detect if we are in a - // Runspace and call a ScriptBlock with exit instead. - if (Runspace.DefaultRunspace != null) - ScriptBlock.Create("Set-Variable -Name LASTEXITCODE -Value $args[0] -Scope Global; exit $args[0]").Invoke(rc); - else - { - // Used for local debugging in Visual Studio - if (System.Diagnostics.Debugger.IsAttached) - { - Console.WriteLine("Press enter to continue..."); - Console.ReadLine(); - } - Environment.Exit(rc); - } - } - - private static void WriteLineModule(string line) - { - Console.WriteLine(line); - } - } -} diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.ModuleUtils.AddType.psm1 b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.ModuleUtils.AddType.psm1 deleted file mode 100644 index 673070263..000000000 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/Ansible.ModuleUtils.AddType.psm1 +++ /dev/null @@ -1,397 +0,0 @@ -# Copyright (c) 2018 Ansible Project -# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) - -Function Add-CSharpType { - <# - .SYNOPSIS - Compiles one or more C# scripts similar to Add-Type. This exposes - more configuration options that are useable within Ansible and it - also allows multiple C# sources to be compiled together. - - .PARAMETER References - [String[]] A collection of C# scripts to compile together. - - .PARAMETER IgnoreWarnings - [Switch] Whether to compile code that contains compiler warnings, by - default warnings will cause a compiler error. - - .PARAMETER PassThru - [Switch] Whether to return the loaded Assembly - - .PARAMETER AnsibleModule - [Ansible.Basic.AnsibleModule] used to derive the TempPath and Debug values. - TempPath is set to the Tmpdir property of the class - IncludeDebugInfo is set when the Ansible verbosity is >= 3 - - .PARAMETER TempPath - [String] The temporary directory in which the dynamic assembly is - compiled to. This file is deleted once compilation is complete. - Cannot be used when AnsibleModule is set. This is a no-op when - running on PSCore. - - .PARAMETER IncludeDebugInfo - [Switch] Whether to include debug information in the compiled - assembly. Cannot be used when AnsibleModule is set. This is a no-op - when running on PSCore. - - .PARAMETER CompileSymbols - [String[]] A list of symbols to be defined during compile time. These are - added to the existing symbols, 'CORECLR', 'WINDOWS', 'UNIX' that are set - conditionalls in this cmdlet. - - .NOTES - The following features were added to control the compiling options from the - code itself. - - * Predefined compiler SYMBOLS - - * CORECLR - Added when running on PowerShell Core. - * WINDOWS - Added when running on Windows. - * UNIX - Added when running on non-Windows. - * X86 - Added when running on a 32-bit process (Ansible 2.10+) - * AMD64 - Added when running on a 64-bit process (Ansible 2.10+) - - * Ignore compiler warnings inline with the following comment inline - - //NoWarn -Name [-CLR Core|Framework] - - * Specify custom assembly references inline - - //AssemblyReference -Name Dll.Location.dll [-CLR Core|Framework] - - # Added in Ansible 2.10 - //AssemblyReference -Type System.Type.Name [-CLR Core|Framework] - - * Create automatic type accelerators to simplify long namespace names (Ansible 2.9+) - - //TypeAccelerator -Name -TypeName - #> - param( - [Parameter(Mandatory = $true)][AllowEmptyCollection()][String[]]$References, - [Switch]$IgnoreWarnings, - [Switch]$PassThru, - [Parameter(Mandatory = $true, ParameterSetName = "Module")][Object]$AnsibleModule, - [Parameter(ParameterSetName = "Manual")][String]$TempPath = $env:TMP, - [Parameter(ParameterSetName = "Manual")][Switch]$IncludeDebugInfo, - [String[]]$CompileSymbols = @() - ) - if ($null -eq $References -or $References.Length -eq 0) { - return - } - - # define special symbols CORECLR, WINDOWS, UNIX if required - # the Is* variables are defined on PSCore, if absent we assume an - # older version of PowerShell under .NET Framework and Windows - $defined_symbols = [System.Collections.ArrayList]$CompileSymbols - - if ([System.IntPtr]::Size -eq 4) { - $defined_symbols.Add('X86') > $null - } - else { - $defined_symbols.Add('AMD64') > $null - } - - $is_coreclr = Get-Variable -Name IsCoreCLR -ErrorAction SilentlyContinue - if ($null -ne $is_coreclr) { - if ($is_coreclr.Value) { - $defined_symbols.Add("CORECLR") > $null - } - } - $is_windows = Get-Variable -Name IsWindows -ErrorAction SilentlyContinue - if ($null -ne $is_windows) { - if ($is_windows.Value) { - $defined_symbols.Add("WINDOWS") > $null - } - else { - $defined_symbols.Add("UNIX") > $null - } - } - else { - $defined_symbols.Add("WINDOWS") > $null - } - - # Store any TypeAccelerators shortcuts the util wants us to set - $type_accelerators = [System.Collections.Generic.List`1[Hashtable]]@() - - # pattern used to find referenced assemblies in the code - $assembly_pattern = [Regex]"//\s*AssemblyReference\s+-(?(Name)|(Type))\s+(?[\w.]*)(\s+-CLR\s+(?Core|Framework))?" - $no_warn_pattern = [Regex]"//\s*NoWarn\s+-Name\s+(?[\w\d]*)(\s+-CLR\s+(?Core|Framework))?" - $type_pattern = [Regex]"//\s*TypeAccelerator\s+-Name\s+(?[\w.]*)\s+-TypeName\s+(?[\w.]*)" - - # PSCore vs PSDesktop use different methods to compile the code, - # PSCore uses Roslyn and can compile the code purely in memory - # without touching the disk while PSDesktop uses CodeDom and csc.exe - # to compile the code. We branch out here and run each - # distribution's method to add our C# code. - if ($is_coreclr) { - # compile the code using Roslyn on PSCore - - # Include the default assemblies using the logic in Add-Type - # https://github.com/PowerShell/PowerShell/blob/master/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs - $assemblies = [System.Collections.Generic.HashSet`1[Microsoft.CodeAnalysis.MetadataReference]]@( - [Microsoft.CodeAnalysis.CompilationReference]::CreateFromFile(([System.Reflection.Assembly]::GetAssembly([PSObject])).Location) - ) - $netcore_app_ref_folder = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName([PSObject].Assembly.Location), "ref") - $lib_assembly_location = [System.IO.Path]::GetDirectoryName([object].Assembly.Location) - foreach ($file in [System.IO.Directory]::EnumerateFiles($netcore_app_ref_folder, "*.dll", [System.IO.SearchOption]::TopDirectoryOnly)) { - $assemblies.Add([Microsoft.CodeAnalysis.MetadataReference]::CreateFromFile($file)) > $null - } - - # loop through the references, parse as a SyntaxTree and get - # referenced assemblies - $ignore_warnings = New-Object -TypeName 'System.Collections.Generic.Dictionary`2[[String], [Microsoft.CodeAnalysis.ReportDiagnostic]]' - $parse_options = ([Microsoft.CodeAnalysis.CSharp.CSharpParseOptions]::Default).WithPreprocessorSymbols($defined_symbols) - $syntax_trees = [System.Collections.Generic.List`1[Microsoft.CodeAnalysis.SyntaxTree]]@() - foreach ($reference in $References) { - # scan through code and add any assemblies that match - # //AssemblyReference -Name ... [-CLR Core] - # //NoWarn -Name ... [-CLR Core] - # //TypeAccelerator -Name ... -TypeName ... - $assembly_matches = $assembly_pattern.Matches($reference) - foreach ($match in $assembly_matches) { - $clr = $match.Groups["CLR"].Value - if ($clr -and $clr -ne "Core") { - continue - } - - $parameter_type = $match.Groups["Parameter"].Value - $assembly_path = $match.Groups["Name"].Value - if ($parameter_type -eq "Type") { - $assembly_path = ([Type]$assembly_path).Assembly.Location - } - else { - if (-not ([System.IO.Path]::IsPathRooted($assembly_path))) { - $assembly_path = Join-Path -Path $lib_assembly_location -ChildPath $assembly_path - } - } - $assemblies.Add([Microsoft.CodeAnalysis.MetadataReference]::CreateFromFile($assembly_path)) > $null - } - $warn_matches = $no_warn_pattern.Matches($reference) - foreach ($match in $warn_matches) { - $clr = $match.Groups["CLR"].Value - if ($clr -and $clr -ne "Core") { - continue - } - $ignore_warnings.Add($match.Groups["Name"], [Microsoft.CodeAnalysis.ReportDiagnostic]::Suppress) - } - $syntax_trees.Add([Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree]::ParseText($reference, $parse_options)) > $null - - $type_matches = $type_pattern.Matches($reference) - foreach ($match in $type_matches) { - $type_accelerators.Add(@{Name = $match.Groups["Name"].Value; TypeName = $match.Groups["TypeName"].Value }) - } - } - - # Release seems to contain the correct line numbers compared to - # debug,may need to keep a closer eye on this in the future - $compiler_options = (New-Object -TypeName Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions -ArgumentList @( - [Microsoft.CodeAnalysis.OutputKind]::DynamicallyLinkedLibrary - )).WithOptimizationLevel([Microsoft.CodeAnalysis.OptimizationLevel]::Release) - - # set warnings to error out if IgnoreWarnings is not set - if (-not $IgnoreWarnings.IsPresent) { - $compiler_options = $compiler_options.WithGeneralDiagnosticOption([Microsoft.CodeAnalysis.ReportDiagnostic]::Error) - $compiler_options = $compiler_options.WithSpecificDiagnosticOptions($ignore_warnings) - } - - # create compilation object - $compilation = [Microsoft.CodeAnalysis.CSharp.CSharpCompilation]::Create( - [System.Guid]::NewGuid().ToString(), - $syntax_trees, - $assemblies, - $compiler_options - ) - - # Load the compiled code and pdb info, we do this so we can - # include line number in a stracktrace - $code_ms = New-Object -TypeName System.IO.MemoryStream - $pdb_ms = New-Object -TypeName System.IO.MemoryStream - try { - $emit_result = $compilation.Emit($code_ms, $pdb_ms) - if (-not $emit_result.Success) { - $errors = [System.Collections.ArrayList]@() - - foreach ($e in $emit_result.Diagnostics) { - # builds the error msg, based on logic in Add-Type - # https://github.com/PowerShell/PowerShell/blob/master/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs#L1239 - if ($null -eq $e.Location.SourceTree) { - $errors.Add($e.ToString()) > $null - continue - } - - $cancel_token = New-Object -TypeName System.Threading.CancellationToken -ArgumentList $false - $text_lines = $e.Location.SourceTree.GetText($cancel_token).Lines - $line_span = $e.Location.GetLineSpan() - - $diagnostic_message = $e.ToString() - $error_line_string = $text_lines[$line_span.StartLinePosition.Line].ToString() - $error_position = $line_span.StartLinePosition.Character - - $sb = New-Object -TypeName System.Text.StringBuilder -ArgumentList ($diagnostic_message.Length + $error_line_string.Length * 2 + 4) - $sb.AppendLine($diagnostic_message) - $sb.AppendLine($error_line_string) - - for ($i = 0; $i -lt $error_line_string.Length; $i++) { - if ([System.Char]::IsWhiteSpace($error_line_string[$i])) { - continue - } - $sb.Append($error_line_string, 0, $i) - $sb.Append(' ', [Math]::Max(0, $error_position - $i)) - $sb.Append("^") - break - } - - $errors.Add($sb.ToString()) > $null - } - - throw [InvalidOperationException]"Failed to compile C# code:`r`n$($errors -join "`r`n")" - } - - $code_ms.Seek(0, [System.IO.SeekOrigin]::Begin) > $null - $pdb_ms.Seek(0, [System.IO.SeekOrigin]::Begin) > $null - $compiled_assembly = [System.Runtime.Loader.AssemblyLoadContext]::Default.LoadFromStream($code_ms, $pdb_ms) - } - finally { - $code_ms.Close() - $pdb_ms.Close() - } - } - else { - # compile the code using CodeDom on PSDesktop - - # configure compile options based on input - if ($PSCmdlet.ParameterSetName -eq "Module") { - $temp_path = $AnsibleModule.Tmpdir - $include_debug = $AnsibleModule.Verbosity -ge 3 - } - else { - $temp_path = $TempPath - $include_debug = $IncludeDebugInfo.IsPresent - } - $compiler_options = [System.Collections.ArrayList]@("/optimize") - if ($defined_symbols.Count -gt 0) { - $compiler_options.Add("/define:" + ([String]::Join(";", $defined_symbols.ToArray()))) > $null - } - - $compile_parameters = New-Object -TypeName System.CodeDom.Compiler.CompilerParameters - $compile_parameters.GenerateExecutable = $false - $compile_parameters.GenerateInMemory = $true - $compile_parameters.TreatWarningsAsErrors = (-not $IgnoreWarnings.IsPresent) - $compile_parameters.IncludeDebugInformation = $include_debug - $compile_parameters.TempFiles = (New-Object -TypeName System.CodeDom.Compiler.TempFileCollection -ArgumentList $temp_path, $false) - - # Add-Type automatically references System.dll, System.Core.dll, - # and System.Management.Automation.dll which we replicate here - $assemblies = [System.Collections.Generic.HashSet`1[String]]@( - "System.dll", - "System.Core.dll", - ([System.Reflection.Assembly]::GetAssembly([PSObject])).Location - ) - - # create a code snippet for each reference and check if we need - # to reference any extra assemblies - $ignore_warnings = [System.Collections.ArrayList]@() - $compile_units = [System.Collections.Generic.List`1[System.CodeDom.CodeSnippetCompileUnit]]@() - foreach ($reference in $References) { - # scan through code and add any assemblies that match - # //AssemblyReference -Name ... [-CLR Framework] - # //NoWarn -Name ... [-CLR Framework] - # //TypeAccelerator -Name ... -TypeName ... - $assembly_matches = $assembly_pattern.Matches($reference) - foreach ($match in $assembly_matches) { - $clr = $match.Groups["CLR"].Value - if ($clr -and $clr -ne "Framework") { - continue - } - - $parameter_type = $match.Groups["Parameter"].Value - $assembly_path = $match.Groups["Name"].Value - if ($parameter_type -eq "Type") { - $assembly_path = ([Type]$assembly_path).Assembly.Location - } - $assemblies.Add($assembly_path) > $null - } - $warn_matches = $no_warn_pattern.Matches($reference) - foreach ($match in $warn_matches) { - $clr = $match.Groups["CLR"].Value - if ($clr -and $clr -ne "Framework") { - continue - } - $warning_id = $match.Groups["Name"].Value - # /nowarn should only contain the numeric part - if ($warning_id.StartsWith("CS")) { - $warning_id = $warning_id.Substring(2) - } - $ignore_warnings.Add($warning_id) > $null - } - $compile_units.Add((New-Object -TypeName System.CodeDom.CodeSnippetCompileUnit -ArgumentList $reference)) > $null - - $type_matches = $type_pattern.Matches($reference) - foreach ($match in $type_matches) { - $type_accelerators.Add(@{Name = $match.Groups["Name"].Value; TypeName = $match.Groups["TypeName"].Value }) - } - } - if ($ignore_warnings.Count -gt 0) { - $compiler_options.Add("/nowarn:" + ([String]::Join(",", $ignore_warnings.ToArray()))) > $null - } - $compile_parameters.ReferencedAssemblies.AddRange($assemblies) - $compile_parameters.CompilerOptions = [String]::Join(" ", $compiler_options.ToArray()) - - # compile the code together and check for errors - $provider = New-Object -TypeName Microsoft.CSharp.CSharpCodeProvider - - # This calls csc.exe which can take compiler options from environment variables. Currently these env vars - # are known to have problems so they are unset: - # LIB - additional library paths will fail the compilation if they are invalid - $originalEnv = @{} - try { - 'LIB' | ForEach-Object -Process { - $value = Get-Item -LiteralPath "Env:\$_" -ErrorAction SilentlyContinue - if ($value) { - $originalEnv[$_] = $value - Remove-Item -LiteralPath "Env:\$_" - } - } - - $compile = $provider.CompileAssemblyFromDom($compile_parameters, $compile_units) - } - finally { - foreach ($kvp in $originalEnv.GetEnumerator()) { - [System.Environment]::SetEnvironmentVariable($kvp.Key, $kvp.Value, "Process") - } - } - - if ($compile.Errors.HasErrors) { - $msg = "Failed to compile C# code: " - foreach ($e in $compile.Errors) { - $msg += "`r`n" + $e.ToString() - } - throw [InvalidOperationException]$msg - } - $compiled_assembly = $compile.CompiledAssembly - } - - $type_accelerator = [PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators") - foreach ($accelerator in $type_accelerators) { - $type_name = $accelerator.TypeName - $found = $false - - foreach ($assembly_type in $compiled_assembly.GetTypes()) { - if ($assembly_type.Name -eq $type_name) { - $type_accelerator::Add($accelerator.Name, $assembly_type) - $found = $true - break - } - } - if (-not $found) { - throw "Failed to find compiled class '$type_name' for custom TypeAccelerator." - } - } - - # return the compiled assembly if PassThru is set. - if ($PassThru) { - return $compiled_assembly - } -} - -Export-ModuleMember -Function Add-CSharpType diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.Basic.cs b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.Basic.cs new file mode 100644 index 000000000..c68281ef1 --- /dev/null +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.Basic.cs @@ -0,0 +1,1489 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security.AccessControl; +using System.Security.Principal; +#if CORECLR +using Newtonsoft.Json; +#else +using System.Web.Script.Serialization; +#endif + +// Newtonsoft.Json may reference a different System.Runtime version (6.x) than loaded by PowerShell 7.3 (7.x). +// Ignore CS1701 so the code can be compiled when warnings are reported as errors. +//NoWarn -Name CS1701 -CLR Core + +// System.Diagnostics.EventLog.dll reference different versioned dlls that are +// loaded in PSCore, ignore CS1702 so the code will ignore this warning +//NoWarn -Name CS1702 -CLR Core + +//AssemblyReference -Type Newtonsoft.Json.JsonConvert -CLR Core +//AssemblyReference -Type System.Diagnostics.EventLog -CLR Core +//AssemblyReference -Type System.Security.AccessControl.NativeObjectSecurity -CLR Core +//AssemblyReference -Type System.Security.AccessControl.DirectorySecurity -CLR Core +//AssemblyReference -Type System.Security.Principal.IdentityReference -CLR Core + +//AssemblyReference -Name System.Web.Extensions.dll -CLR Framework + +namespace Ansible.Basic +{ + public class AnsibleModule + { + public delegate void ExitHandler(int rc); + public static ExitHandler Exit = new ExitHandler(ExitModule); + + public delegate void WriteLineHandler(string line); + public static WriteLineHandler WriteLine = new WriteLineHandler(WriteLineModule); + + public static bool _DebugArgSpec = false; + + private static List BOOLEANS_TRUE = new List() { "y", "yes", "on", "1", "true", "t", "1.0" }; + private static List BOOLEANS_FALSE = new List() { "n", "no", "off", "0", "false", "f", "0.0" }; + + private string remoteTmp = Path.GetTempPath(); + private string tmpdir = null; + private HashSet noLogValues = new HashSet(); + private List optionsContext = new List(); + private List warnings = new List(); + private List> deprecations = new List>(); + private List cleanupFiles = new List(); + + private Dictionary passVars = new Dictionary() + { + // null values means no mapping, not used in Ansible.Basic.AnsibleModule + { "check_mode", "CheckMode" }, + { "debug", "DebugMode" }, + { "diff", "DiffMode" }, + { "keep_remote_files", "KeepRemoteFiles" }, + { "module_name", "ModuleName" }, + { "no_log", "NoLog" }, + { "remote_tmp", "remoteTmp" }, + { "selinux_special_fs", null }, + { "shell_executable", null }, + { "socket", null }, + { "string_conversion_action", null }, + { "syslog_facility", null }, + { "tmpdir", "tmpdir" }, + { "verbosity", "Verbosity" }, + { "version", "AnsibleVersion" }, + }; + private List passBools = new List() { "check_mode", "debug", "diff", "keep_remote_files", "no_log" }; + private List passInts = new List() { "verbosity" }; + private Dictionary> specDefaults = new Dictionary>() + { + // key - (default, type) - null is freeform + { "apply_defaults", new List() { false, typeof(bool) } }, + { "aliases", new List() { typeof(List), typeof(List) } }, + { "choices", new List() { typeof(List), typeof(List) } }, + { "default", new List() { null, null } }, + { "deprecated_aliases", new List() { typeof(List), typeof(List) } }, + { "elements", new List() { null, null } }, + { "mutually_exclusive", new List() { typeof(List>), typeof(List) } }, + { "no_log", new List() { false, typeof(bool) } }, + { "options", new List() { typeof(Hashtable), typeof(Hashtable) } }, + { "removed_in_version", new List() { null, typeof(string) } }, + { "removed_at_date", new List() { null, typeof(DateTime) } }, + { "removed_from_collection", new List() { null, typeof(string) } }, + { "required", new List() { false, typeof(bool) } }, + { "required_by", new List() { typeof(Hashtable), typeof(Hashtable) } }, + { "required_if", new List() { typeof(List>), typeof(List) } }, + { "required_one_of", new List() { typeof(List>), typeof(List) } }, + { "required_together", new List() { typeof(List>), typeof(List) } }, + { "supports_check_mode", new List() { false, typeof(bool) } }, + { "type", new List() { "str", null } }, + }; + private Dictionary optionTypes = new Dictionary() + { + { "bool", new Func(ParseBool) }, + { "dict", new Func>(ParseDict) }, + { "float", new Func(ParseFloat) }, + { "int", new Func(ParseInt) }, + { "json", new Func(ParseJson) }, + { "list", new Func>(ParseList) }, + { "path", new Func(ParsePath) }, + { "raw", new Func(ParseRaw) }, + { "sid", new Func(ParseSid) }, + { "str", new Func(ParseStr) }, + }; + + public Dictionary Diff = new Dictionary(); + public IDictionary Params = null; + public Dictionary Result = new Dictionary() { { "changed", false } }; + + public bool CheckMode { get; private set; } + public bool DebugMode { get; private set; } + public bool DiffMode { get; private set; } + public bool KeepRemoteFiles { get; private set; } + public string ModuleName { get; private set; } + public bool NoLog { get; private set; } + public int Verbosity { get; private set; } + public string AnsibleVersion { get; private set; } + + public string Tmpdir + { + get + { + if (tmpdir == null) + { +#if WINDOWS + SecurityIdentifier user = WindowsIdentity.GetCurrent().User; + DirectorySecurity dirSecurity = new DirectorySecurity(); + dirSecurity.SetOwner(user); + dirSecurity.SetAccessRuleProtection(true, false); // disable inheritance rules + FileSystemAccessRule ace = new FileSystemAccessRule(user, FileSystemRights.FullControl, + InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, + PropagationFlags.None, AccessControlType.Allow); + dirSecurity.AddAccessRule(ace); + + string baseDir = Path.GetFullPath(Environment.ExpandEnvironmentVariables(remoteTmp)); + if (!Directory.Exists(baseDir)) + { + string failedMsg = null; + try + { +#if CORECLR + DirectoryInfo createdDir = Directory.CreateDirectory(baseDir); + FileSystemAclExtensions.SetAccessControl(createdDir, dirSecurity); +#else + Directory.CreateDirectory(baseDir, dirSecurity); +#endif + } + catch (Exception e) + { + failedMsg = String.Format("Failed to create base tmpdir '{0}': {1}", baseDir, e.Message); + } + + if (failedMsg != null) + { + string envTmp = Path.GetTempPath(); + Warn(String.Format("Unable to use '{0}' as temporary directory, falling back to system tmp '{1}': {2}", baseDir, envTmp, failedMsg)); + baseDir = envTmp; + } + else + { + NTAccount currentUser = (NTAccount)user.Translate(typeof(NTAccount)); + string warnMsg = String.Format("Module remote_tmp {0} did not exist and was created with FullControl to {1}, ", baseDir, currentUser.ToString()); + warnMsg += "this may cause issues when running as another user. To avoid this, create the remote_tmp dir with the correct permissions manually"; + Warn(warnMsg); + } + } + + string dateTime = DateTime.Now.ToFileTime().ToString(); + string dirName = String.Format("ansible-moduletmp-{0}-{1}", dateTime, new Random().Next(0, int.MaxValue)); + string newTmpdir = Path.Combine(baseDir, dirName); +#if CORECLR + DirectoryInfo tmpdirInfo = Directory.CreateDirectory(newTmpdir); + FileSystemAclExtensions.SetAccessControl(tmpdirInfo, dirSecurity); +#else + Directory.CreateDirectory(newTmpdir, dirSecurity); +#endif + tmpdir = newTmpdir; + + if (!KeepRemoteFiles) + cleanupFiles.Add(tmpdir); +#else + throw new NotImplementedException("Tmpdir is only supported on Windows"); +#endif + } + return tmpdir; + } + } + + public AnsibleModule(string[] args, IDictionary argumentSpec, IDictionary[] fragments = null) + { + // NoLog is not set yet, we cannot rely on FailJson to sanitize the output + // Do the minimum amount to get this running before we actually parse the params + Dictionary aliases = new Dictionary(); + try + { + ValidateArgumentSpec(argumentSpec); + + // Merge the fragments if present into the main arg spec. + if (fragments != null) + { + foreach (IDictionary fragment in fragments) + { + ValidateArgumentSpec(fragment); + MergeFragmentSpec(argumentSpec, fragment); + } + } + + // Used by ansible-test to retrieve the module argument spec, not designed for public use. + if (_DebugArgSpec) + { + // Cannot call exit here because it will be caught with the catch (Exception e) below. Instead + // just throw a new exception with a specific message and the exception block will handle it. + ScriptBlock.Create("Set-Variable -Name ansibleTestArgSpec -Value $args[0] -Scope Global" + ).Invoke(argumentSpec); + throw new Exception("ansible-test validate-modules check"); + } + + // Now make sure all the metadata keys are set to their defaults, this must be done after we've + // potentially output the arg spec for ansible-test. + SetArgumentSpecDefaults(argumentSpec); + + Params = GetParams(args); + aliases = GetAliases(argumentSpec, Params); + SetNoLogValues(argumentSpec, Params); + } + catch (Exception e) + { + if (e.Message == "ansible-test validate-modules check") + Exit(0); + + Dictionary result = new Dictionary + { + { "failed", true }, + { "msg", String.Format("internal error: {0}", e.Message) }, + { "exception", e.ToString() } + }; + WriteLine(ToJson(result)); + Exit(1); + } + + // Initialise public properties to the defaults before we parse the actual inputs + CheckMode = false; + DebugMode = false; + DiffMode = false; + KeepRemoteFiles = false; + ModuleName = "undefined win module"; + NoLog = (bool)argumentSpec["no_log"]; + Verbosity = 0; + AppDomain.CurrentDomain.ProcessExit += CleanupFiles; + + List legalInputs = passVars.Keys.Select(v => "_ansible_" + v).ToList(); + legalInputs.AddRange(((IDictionary)argumentSpec["options"]).Keys.Cast().ToList()); + legalInputs.AddRange(aliases.Keys.Cast().ToList()); + CheckArguments(argumentSpec, Params, legalInputs); + + // Set a Ansible friendly invocation value in the result object + Dictionary invocation = new Dictionary() { { "module_args", Params } }; + Result["invocation"] = RemoveNoLogValues(invocation, noLogValues); + + if (!NoLog) + LogEvent(String.Format("Invoked with:\r\n {0}", FormatLogData(Params, 2)), sanitise: false); + } + + public static AnsibleModule Create(string[] args, IDictionary argumentSpec, IDictionary[] fragments = null) + { + return new AnsibleModule(args, argumentSpec, fragments); + } + + public void Debug(string message) + { + if (DebugMode) + LogEvent(String.Format("[DEBUG] {0}", message)); + } + + public void Deprecate(string message, string version) + { + Deprecate(message, version, null); + } + + public void Deprecate(string message, string version, string collectionName) + { + deprecations.Add(new Dictionary() { + { "msg", message }, { "version", version }, { "collection_name", collectionName } }); + LogEvent(String.Format("[DEPRECATION WARNING] {0} {1}", message, version)); + } + + public void Deprecate(string message, DateTime date) + { + Deprecate(message, date, null); + } + + public void Deprecate(string message, DateTime date, string collectionName) + { + string isoDate = date.ToString("yyyy-MM-dd"); + deprecations.Add(new Dictionary() { + { "msg", message }, { "date", isoDate }, { "collection_name", collectionName } }); + LogEvent(String.Format("[DEPRECATION WARNING] {0} {1}", message, isoDate)); + } + + public void ExitJson() + { + WriteLine(GetFormattedResults(Result)); + CleanupFiles(null, null); + Exit(0); + } + + public void FailJson(string message) { FailJson(message, null, null); } + public void FailJson(string message, ErrorRecord psErrorRecord) { FailJson(message, psErrorRecord, null); } + public void FailJson(string message, Exception exception) { FailJson(message, null, exception); } + private void FailJson(string message, ErrorRecord psErrorRecord, Exception exception) + { + Result["failed"] = true; + Result["msg"] = RemoveNoLogValues(message, noLogValues); + + + if (!Result.ContainsKey("exception") && (Verbosity > 2 || DebugMode)) + { + if (psErrorRecord != null) + { + string traceback = String.Format("{0}\r\n{1}", psErrorRecord.ToString(), psErrorRecord.InvocationInfo.PositionMessage); + traceback += String.Format("\r\n + CategoryInfo : {0}", psErrorRecord.CategoryInfo.ToString()); + traceback += String.Format("\r\n + FullyQualifiedErrorId : {0}", psErrorRecord.FullyQualifiedErrorId.ToString()); + traceback += String.Format("\r\n\r\nScriptStackTrace:\r\n{0}", psErrorRecord.ScriptStackTrace); + Result["exception"] = traceback; + } + else if (exception != null) + Result["exception"] = exception.ToString(); + } + + WriteLine(GetFormattedResults(Result)); + CleanupFiles(null, null); + Exit(1); + } + + public void LogEvent(string message, EventLogEntryType logEntryType = EventLogEntryType.Information, bool sanitise = true) + { + if (NoLog) + return; + +#if WINDOWS + string logSource = "Ansible"; + bool logSourceExists = false; + try + { + logSourceExists = EventLog.SourceExists(logSource); + } + catch (System.Security.SecurityException) { } // non admin users may not have permission + + if (!logSourceExists) + { + try + { + EventLog.CreateEventSource(logSource, "Application"); + } + catch (System.Security.SecurityException) + { + // Cannot call Warn as that calls LogEvent and we get stuck in a loop + warnings.Add(String.Format("Access error when creating EventLog source {0}, logging to the Application source instead", logSource)); + logSource = "Application"; + } + } + if (sanitise) + message = (string)RemoveNoLogValues(message, noLogValues); + message = String.Format("{0} - {1}", ModuleName, message); + + using (EventLog eventLog = new EventLog("Application")) + { + eventLog.Source = logSource; + try + { + eventLog.WriteEntry(message, logEntryType, 0); + } + catch (System.InvalidOperationException) { } // Ignore permission errors on the Application event log + catch (System.Exception e) + { + // Cannot call Warn as that calls LogEvent and we get stuck in a loop + warnings.Add(String.Format("Unknown error when creating event log entry: {0}", e.Message)); + } + } +#else + // Windows Event Log is only available on Windows + return; +#endif + } + + public void Warn(string message) + { + warnings.Add(message); + LogEvent(String.Format("[WARNING] {0}", message), EventLogEntryType.Warning); + } + + public static object FromJson(string json) { return FromJson(json); } + public static T FromJson(string json) + { +#if CORECLR + return JsonConvert.DeserializeObject(json); +#else + JavaScriptSerializer jss = new JavaScriptSerializer(); + jss.MaxJsonLength = int.MaxValue; + jss.RecursionLimit = int.MaxValue; + return jss.Deserialize(json); +#endif + } + + public static string ToJson(object obj) + { + // Using PowerShell to serialize the JSON is preferable over the native .NET libraries as it handles + // PS Objects a lot better than the alternatives. In case we are debugging in Visual Studio we have a + // fallback to the other libraries as we won't be dealing with PowerShell objects there. + if (Runspace.DefaultRunspace != null) + { + PSObject rawOut = ScriptBlock.Create("ConvertTo-Json -InputObject $args[0] -Depth 99 -Compress").Invoke(obj)[0]; + return rawOut.BaseObject as string; + } + else + { +#if CORECLR + return JsonConvert.SerializeObject(obj); +#else + JavaScriptSerializer jss = new JavaScriptSerializer(); + jss.MaxJsonLength = int.MaxValue; + jss.RecursionLimit = int.MaxValue; + return jss.Serialize(obj); +#endif + } + } + + public static IDictionary GetParams(string[] args) + { + if (args.Length > 0) + { + string inputJson = File.ReadAllText(args[0]); + Dictionary rawParams = FromJson>(inputJson); + if (!rawParams.ContainsKey("ANSIBLE_MODULE_ARGS")) + throw new ArgumentException("Module was unable to get ANSIBLE_MODULE_ARGS value from the argument path json"); + return (IDictionary)rawParams["ANSIBLE_MODULE_ARGS"]; + } + else + { + // $complex_args is already a Hashtable, no need to waste time converting to a dictionary + PSObject rawArgs = ScriptBlock.Create("$complex_args").Invoke()[0]; + return rawArgs.BaseObject as Hashtable; + } + } + + public static bool ParseBool(object value) + { + if (value.GetType() == typeof(bool)) + return (bool)value; + + List booleans = new List(); + booleans.AddRange(BOOLEANS_TRUE); + booleans.AddRange(BOOLEANS_FALSE); + + string stringValue = ParseStr(value).ToLowerInvariant().Trim(); + if (BOOLEANS_TRUE.Contains(stringValue)) + return true; + else if (BOOLEANS_FALSE.Contains(stringValue)) + return false; + + string msg = String.Format("The value '{0}' is not a valid boolean. Valid booleans include: {1}", + stringValue, String.Join(", ", booleans)); + throw new ArgumentException(msg); + } + + public static Dictionary ParseDict(object value) + { + Type valueType = value.GetType(); + if (valueType == typeof(Dictionary)) + return (Dictionary)value; + else if (value is IDictionary) + return ((IDictionary)value).Cast().ToDictionary(kvp => (string)kvp.Key, kvp => kvp.Value); + else if (valueType == typeof(string)) + { + string stringValue = (string)value; + if (stringValue.StartsWith("{") && stringValue.EndsWith("}")) + return FromJson>((string)value); + else if (stringValue.IndexOfAny(new char[1] { '=' }) != -1) + { + List fields = new List(); + List fieldBuffer = new List(); + char? inQuote = null; + bool inEscape = false; + string field; + + foreach (char c in stringValue.ToCharArray()) + { + if (inEscape) + { + fieldBuffer.Add(c); + inEscape = false; + } + else if (c == '\\') + inEscape = true; + else if (inQuote == null && (c == '\'' || c == '"')) + inQuote = c; + else if (inQuote != null && c == inQuote) + inQuote = null; + else if (inQuote == null && (c == ',' || c == ' ')) + { + field = String.Join("", fieldBuffer); + if (field != "") + fields.Add(field); + fieldBuffer = new List(); + } + else + fieldBuffer.Add(c); + } + + field = String.Join("", fieldBuffer); + if (field != "") + fields.Add(field); + + return fields.Distinct().Select(i => i.Split(new[] { '=' }, 2)).ToDictionary(i => i[0], i => i.Length > 1 ? (object)i[1] : null); + } + else + throw new ArgumentException("string cannot be converted to a dict, must either be a JSON string or in the key=value form"); + } + + throw new ArgumentException(String.Format("{0} cannot be converted to a dict", valueType.FullName)); + } + + public static float ParseFloat(object value) + { + if (value.GetType() == typeof(float)) + return (float)value; + + string valueStr = ParseStr(value); + return float.Parse(valueStr); + } + + public static int ParseInt(object value) + { + Type valueType = value.GetType(); + if (valueType == typeof(int)) + return (int)value; + else + return Int32.Parse(ParseStr(value)); + } + + public static string ParseJson(object value) + { + // mostly used to ensure a dict is a json string as it may + // have been converted on the controller side + Type valueType = value.GetType(); + if (value is IDictionary) + return ToJson(value); + else if (valueType == typeof(string)) + return (string)value; + else + throw new ArgumentException(String.Format("{0} cannot be converted to json", valueType.FullName)); + } + + public static List ParseList(object value) + { + if (value == null) + return null; + + Type valueType = value.GetType(); + if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) + return (List)value; + else if (valueType == typeof(ArrayList)) + return ((ArrayList)value).Cast().ToList(); + else if (valueType.IsArray) + return ((object[])value).ToList(); + else if (valueType == typeof(string)) + return ((string)value).Split(',').Select(s => s.Trim()).ToList(); + else if (valueType == typeof(int)) + return new List() { value }; + else + throw new ArgumentException(String.Format("{0} cannot be converted to a list", valueType.FullName)); + } + + public static string ParsePath(object value) + { + string stringValue = ParseStr(value); + + // do not validate, expand the env vars if it starts with \\?\ as + // it is a special path designed for the NT kernel to interpret + if (stringValue.StartsWith(@"\\?\")) + return stringValue; + + stringValue = Environment.ExpandEnvironmentVariables(stringValue); + if (stringValue.IndexOfAny(Path.GetInvalidPathChars()) != -1) + throw new ArgumentException("string value contains invalid path characters, cannot convert to path"); + + // will fire an exception if it contains any invalid chars + Path.GetFullPath(stringValue); + return stringValue; + } + + public static object ParseRaw(object value) { return value; } + + public static SecurityIdentifier ParseSid(object value) + { + string stringValue = ParseStr(value); + + try + { + return new SecurityIdentifier(stringValue); + } + catch (ArgumentException) { } // ignore failures string may not have been a SID + + NTAccount account = new NTAccount(stringValue); + return (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier)); + } + + public static string ParseStr(object value) { return value.ToString(); } + + private void ValidateArgumentSpec(IDictionary argumentSpec) + { + Dictionary changedValues = new Dictionary(); + foreach (DictionaryEntry entry in argumentSpec) + { + string key = (string)entry.Key; + + // validate the key is a valid argument spec key + if (!specDefaults.ContainsKey(key)) + { + string msg = String.Format("argument spec entry contains an invalid key '{0}', valid keys: {1}", + key, String.Join(", ", specDefaults.Keys)); + throw new ArgumentException(FormatOptionsContext(msg, " - ")); + } + + // ensure the value is casted to the type we expect + Type optionType = null; + if (entry.Value != null) + optionType = (Type)specDefaults[key][1]; + if (optionType != null) + { + Type actualType = entry.Value.GetType(); + bool invalid = false; + if (optionType.IsGenericType && optionType.GetGenericTypeDefinition() == typeof(List<>)) + { + // verify the actual type is not just a single value of the list type + Type entryType = optionType.GetGenericArguments()[0]; + object[] arrayElementTypes = new object[] + { + null, // ArrayList does not have an ElementType + entryType, + typeof(object), // Hope the object is actually entryType or it can at least be casted. + }; + + bool isArray = entry.Value is IList && arrayElementTypes.Contains(actualType.GetElementType()); + if (actualType == entryType || isArray) + { + object rawArray; + if (isArray) + rawArray = entry.Value; + else + rawArray = new object[1] { entry.Value }; + + MethodInfo castMethod = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(entryType); + MethodInfo toListMethod = typeof(Enumerable).GetMethod("ToList").MakeGenericMethod(entryType); + + var enumerable = castMethod.Invoke(null, new object[1] { rawArray }); + var newList = toListMethod.Invoke(null, new object[1] { enumerable }); + changedValues.Add(key, newList); + } + else if (actualType != optionType && !(actualType == typeof(List))) + invalid = true; + } + else + invalid = actualType != optionType; + + if (invalid) + { + string msg = String.Format("argument spec for '{0}' did not match expected type {1}: actual type {2}", + key, optionType.FullName, actualType.FullName); + throw new ArgumentException(FormatOptionsContext(msg, " - ")); + } + } + + // recursively validate the spec + if (key == "options" && entry.Value != null) + { + IDictionary optionsSpec = (IDictionary)entry.Value; + foreach (DictionaryEntry optionEntry in optionsSpec) + { + optionsContext.Add((string)optionEntry.Key); + IDictionary optionMeta = (IDictionary)optionEntry.Value; + ValidateArgumentSpec(optionMeta); + optionsContext.RemoveAt(optionsContext.Count - 1); + } + } + + // validate the type and elements key type values are known types + if (key == "type" || key == "elements" && entry.Value != null) + { + Type valueType = entry.Value.GetType(); + if (valueType == typeof(string)) + { + string typeValue = (string)entry.Value; + if (!optionTypes.ContainsKey(typeValue)) + { + string msg = String.Format("{0} '{1}' is unsupported", key, typeValue); + msg = String.Format("{0}. Valid types are: {1}", FormatOptionsContext(msg, " - "), String.Join(", ", optionTypes.Keys)); + throw new ArgumentException(msg); + } + } + else if (!(entry.Value is Delegate)) + { + string msg = String.Format("{0} must either be a string or delegate, was: {1}", key, valueType.FullName); + throw new ArgumentException(FormatOptionsContext(msg, " - ")); + } + } + } + + // Outside of the spec iterator, change the values that were casted above + foreach (KeyValuePair changedValue in changedValues) + argumentSpec[changedValue.Key] = changedValue.Value; + } + + private void MergeFragmentSpec(IDictionary argumentSpec, IDictionary fragment) + { + foreach (DictionaryEntry fragmentEntry in fragment) + { + string fragmentKey = fragmentEntry.Key.ToString(); + + if (argumentSpec.Contains(fragmentKey)) + { + // We only want to add new list entries and merge dictionary new keys and values. Leave the other + // values as is in the argument spec as that takes priority over the fragment. + if (fragmentEntry.Value is IDictionary) + { + MergeFragmentSpec((IDictionary)argumentSpec[fragmentKey], (IDictionary)fragmentEntry.Value); + } + else if (fragmentEntry.Value is IList) + { + IList specValue = (IList)argumentSpec[fragmentKey]; + foreach (object fragmentValue in (IList)fragmentEntry.Value) + specValue.Add(fragmentValue); + } + } + else + argumentSpec[fragmentKey] = fragmentEntry.Value; + } + } + + private void SetArgumentSpecDefaults(IDictionary argumentSpec) + { + foreach (KeyValuePair> metadataEntry in specDefaults) + { + List defaults = metadataEntry.Value; + object defaultValue = defaults[0]; + if (defaultValue != null && defaultValue.GetType() == typeof(Type).GetType()) + defaultValue = Activator.CreateInstance((Type)defaultValue); + + if (!argumentSpec.Contains(metadataEntry.Key)) + argumentSpec[metadataEntry.Key] = defaultValue; + } + + // Recursively set the defaults for any inner options. + foreach (DictionaryEntry entry in argumentSpec) + { + if (entry.Value == null || entry.Key.ToString() != "options") + continue; + + IDictionary optionsSpec = (IDictionary)entry.Value; + foreach (DictionaryEntry optionEntry in optionsSpec) + { + optionsContext.Add((string)optionEntry.Key); + IDictionary optionMeta = (IDictionary)optionEntry.Value; + SetArgumentSpecDefaults(optionMeta); + optionsContext.RemoveAt(optionsContext.Count - 1); + } + } + } + + private Dictionary GetAliases(IDictionary argumentSpec, IDictionary parameters) + { + Dictionary aliasResults = new Dictionary(); + + foreach (DictionaryEntry entry in (IDictionary)argumentSpec["options"]) + { + string k = (string)entry.Key; + Hashtable v = (Hashtable)entry.Value; + + List aliases = (List)v["aliases"]; + object defaultValue = v["default"]; + bool required = (bool)v["required"]; + + if (defaultValue != null && required) + throw new ArgumentException(String.Format("required and default are mutually exclusive for {0}", k)); + + foreach (string alias in aliases) + { + aliasResults.Add(alias, k); + if (parameters.Contains(alias)) + parameters[k] = parameters[alias]; + } + + List deprecatedAliases = (List)v["deprecated_aliases"]; + foreach (Hashtable depInfo in deprecatedAliases) + { + foreach (string keyName in new List { "name" }) + { + if (!depInfo.ContainsKey(keyName)) + { + string msg = String.Format("{0} is required in a deprecated_aliases entry", keyName); + throw new ArgumentException(FormatOptionsContext(msg, " - ")); + } + } + if (!depInfo.ContainsKey("version") && !depInfo.ContainsKey("date")) + { + string msg = "One of version or date is required in a deprecated_aliases entry"; + throw new ArgumentException(FormatOptionsContext(msg, " - ")); + } + if (depInfo.ContainsKey("version") && depInfo.ContainsKey("date")) + { + string msg = "Only one of version or date is allowed in a deprecated_aliases entry"; + throw new ArgumentException(FormatOptionsContext(msg, " - ")); + } + if (depInfo.ContainsKey("date") && depInfo["date"].GetType() != typeof(DateTime)) + { + string msg = "A deprecated_aliases date must be a DateTime object"; + throw new ArgumentException(FormatOptionsContext(msg, " - ")); + } + string collectionName = null; + if (depInfo.ContainsKey("collection_name")) + { + collectionName = (string)depInfo["collection_name"]; + } + string aliasName = (string)depInfo["name"]; + + if (parameters.Contains(aliasName)) + { + string msg = String.Format("Alias '{0}' is deprecated. See the module docs for more information", aliasName); + if (depInfo.ContainsKey("version")) + { + string depVersion = (string)depInfo["version"]; + Deprecate(FormatOptionsContext(msg, " - "), depVersion, collectionName); + } + if (depInfo.ContainsKey("date")) + { + DateTime depDate = (DateTime)depInfo["date"]; + Deprecate(FormatOptionsContext(msg, " - "), depDate, collectionName); + } + } + } + } + + return aliasResults; + } + + private void SetNoLogValues(IDictionary argumentSpec, IDictionary parameters) + { + foreach (DictionaryEntry entry in (IDictionary)argumentSpec["options"]) + { + string k = (string)entry.Key; + Hashtable v = (Hashtable)entry.Value; + + if ((bool)v["no_log"]) + { + object noLogObject = parameters.Contains(k) ? parameters[k] : null; + string noLogString = noLogObject == null ? "" : noLogObject.ToString(); + if (!String.IsNullOrEmpty(noLogString)) + noLogValues.Add(noLogString); + } + string collectionName = null; + if (v.ContainsKey("removed_from_collection")) + { + collectionName = (string)v["removed_from_collection"]; + } + + object removedInVersion = v["removed_in_version"]; + if (removedInVersion != null && parameters.Contains(k)) + Deprecate(String.Format("Param '{0}' is deprecated. See the module docs for more information", k), + removedInVersion.ToString(), collectionName); + + object removedAtDate = v["removed_at_date"]; + if (removedAtDate != null && parameters.Contains(k)) + Deprecate(String.Format("Param '{0}' is deprecated. See the module docs for more information", k), + (DateTime)removedAtDate, collectionName); + } + } + + private void CheckArguments(IDictionary spec, IDictionary param, List legalInputs) + { + // initially parse the params and check for unsupported ones and set internal vars + CheckUnsupportedArguments(param, legalInputs); + + // Only run this check if we are at the root argument (optionsContext.Count == 0) + if (CheckMode && !(bool)spec["supports_check_mode"] && optionsContext.Count == 0) + { + Result["skipped"] = true; + Result["msg"] = String.Format("remote module ({0}) does not support check mode", ModuleName); + ExitJson(); + } + IDictionary optionSpec = (IDictionary)spec["options"]; + + CheckMutuallyExclusive(param, (IList)spec["mutually_exclusive"]); + CheckRequiredArguments(optionSpec, param); + + // set the parameter types based on the type spec value + foreach (DictionaryEntry entry in optionSpec) + { + string k = (string)entry.Key; + Hashtable v = (Hashtable)entry.Value; + + object value = param.Contains(k) ? param[k] : null; + if (value != null) + { + // convert the current value to the wanted type + Delegate typeConverter; + string type; + if (v["type"].GetType() == typeof(string)) + { + type = (string)v["type"]; + typeConverter = optionTypes[type]; + } + else + { + type = "delegate"; + typeConverter = (Delegate)v["type"]; + } + + try + { + value = typeConverter.DynamicInvoke(value); + param[k] = value; + } + catch (Exception e) + { + string msg = String.Format("argument for {0} is of type {1} and we were unable to convert to {2}: {3}", + k, value.GetType(), type, e.InnerException.Message); + FailJson(FormatOptionsContext(msg)); + } + + // ensure it matches the choices if there are choices set + List choices = ((List)v["choices"]).Select(x => x.ToString()).Cast().ToList(); + if (choices.Count > 0) + { + List values; + string choiceMsg; + if (type == "list") + { + values = ((List)value).Select(x => x.ToString()).Cast().ToList(); + choiceMsg = "one or more of"; + } + else + { + values = new List() { value.ToString() }; + choiceMsg = "one of"; + } + + List diffList = values.Except(choices, StringComparer.OrdinalIgnoreCase).ToList(); + List caseDiffList = values.Except(choices).ToList(); + if (diffList.Count > 0) + { + string msg = String.Format("value of {0} must be {1}: {2}. Got no match for: {3}", + k, choiceMsg, String.Join(", ", choices), String.Join(", ", diffList)); + FailJson(FormatOptionsContext(msg)); + } + /* + For now we will just silently accept case insensitive choices, uncomment this if we want to add it back in + else if (caseDiffList.Count > 0) + { + // For backwards compatibility with Legacy.psm1 we need to be matching choices that are not case sensitive. + // We will warn the user it was case insensitive and tell them this will become case sensitive in the future. + string msg = String.Format( + "value of {0} was a case insensitive match of {1}: {2}. Checking of choices will be case sensitive in a future Ansible release. Case insensitive matches were: {3}", + k, choiceMsg, String.Join(", ", choices), String.Join(", ", caseDiffList.Select(x => RemoveNoLogValues(x, noLogValues))) + ); + Warn(FormatOptionsContext(msg)); + }*/ + } + } + } + + CheckRequiredTogether(param, (IList)spec["required_together"]); + CheckRequiredOneOf(param, (IList)spec["required_one_of"]); + CheckRequiredIf(param, (IList)spec["required_if"]); + CheckRequiredBy(param, (IDictionary)spec["required_by"]); + + // finally ensure all missing parameters are set to null and handle sub options + foreach (DictionaryEntry entry in optionSpec) + { + string k = (string)entry.Key; + IDictionary v = (IDictionary)entry.Value; + + if (!param.Contains(k)) + param[k] = null; + + CheckSubOption(param, k, v); + } + } + + private void CheckUnsupportedArguments(IDictionary param, List legalInputs) + { + HashSet unsupportedParameters = new HashSet(); + HashSet caseUnsupportedParameters = new HashSet(); + List removedParameters = new List(); + + foreach (DictionaryEntry entry in param) + { + string paramKey = (string)entry.Key; + if (!legalInputs.Contains(paramKey, StringComparer.OrdinalIgnoreCase)) + unsupportedParameters.Add(paramKey); + else if (!legalInputs.Contains(paramKey)) + // For backwards compatibility we do not care about the case but we need to warn the users as this will + // change in a future Ansible release. + caseUnsupportedParameters.Add(paramKey); + else if (paramKey.StartsWith("_ansible_")) + { + removedParameters.Add(paramKey); + string key = paramKey.Replace("_ansible_", ""); + // skip setting NoLog if NoLog is already set to true (set by the module) + // or there's no mapping for this key + if ((key == "no_log" && NoLog == true) || (passVars[key] == null)) + continue; + + object value = entry.Value; + if (passBools.Contains(key)) + value = ParseBool(value); + else if (passInts.Contains(key)) + value = ParseInt(value); + + string propertyName = passVars[key]; + PropertyInfo property = typeof(AnsibleModule).GetProperty(propertyName); + FieldInfo field = typeof(AnsibleModule).GetField(propertyName, BindingFlags.NonPublic | BindingFlags.Instance); + if (property != null) + property.SetValue(this, value, null); + else if (field != null) + field.SetValue(this, value); + else + FailJson(String.Format("implementation error: unknown AnsibleModule property {0}", propertyName)); + } + } + foreach (string parameter in removedParameters) + param.Remove(parameter); + + if (unsupportedParameters.Count > 0) + { + legalInputs.RemoveAll(x => passVars.Keys.Contains(x.Replace("_ansible_", ""))); + string msg = String.Format("Unsupported parameters for ({0}) module: {1}", ModuleName, String.Join(", ", unsupportedParameters)); + msg = String.Format("{0}. Supported parameters include: {1}", FormatOptionsContext(msg), String.Join(", ", legalInputs)); + FailJson(msg); + } + + /* + // Uncomment when we want to start warning users around options that are not a case sensitive match to the spec + if (caseUnsupportedParameters.Count > 0) + { + legalInputs.RemoveAll(x => passVars.Keys.Contains(x.Replace("_ansible_", ""))); + string msg = String.Format("Parameters for ({0}) was a case insensitive match: {1}", ModuleName, String.Join(", ", caseUnsupportedParameters)); + msg = String.Format("{0}. Module options will become case sensitive in a future Ansible release. Supported parameters include: {1}", + FormatOptionsContext(msg), String.Join(", ", legalInputs)); + Warn(msg); + }*/ + + // Make sure we convert all the incorrect case params to the ones set by the module spec + foreach (string key in caseUnsupportedParameters) + { + string correctKey = legalInputs[legalInputs.FindIndex(s => s.Equals(key, StringComparison.OrdinalIgnoreCase))]; + object value = param[key]; + param.Remove(key); + param.Add(correctKey, value); + } + } + + private void CheckMutuallyExclusive(IDictionary param, IList mutuallyExclusive) + { + if (mutuallyExclusive == null) + return; + + foreach (object check in mutuallyExclusive) + { + List mutualCheck = ((IList)check).Cast().ToList(); + int count = 0; + foreach (string entry in mutualCheck) + if (param.Contains(entry)) + count++; + + if (count > 1) + { + string msg = String.Format("parameters are mutually exclusive: {0}", String.Join(", ", mutualCheck)); + FailJson(FormatOptionsContext(msg)); + } + } + } + + private void CheckRequiredArguments(IDictionary spec, IDictionary param) + { + List missing = new List(); + foreach (DictionaryEntry entry in spec) + { + string k = (string)entry.Key; + Hashtable v = (Hashtable)entry.Value; + + // set defaults for values not already set + object defaultValue = v["default"]; + if (defaultValue != null && !param.Contains(k)) + param[k] = defaultValue; + + // check required arguments + bool required = (bool)v["required"]; + if (required && !param.Contains(k)) + missing.Add(k); + } + if (missing.Count > 0) + { + string msg = String.Format("missing required arguments: {0}", String.Join(", ", missing)); + FailJson(FormatOptionsContext(msg)); + } + } + + private void CheckRequiredTogether(IDictionary param, IList requiredTogether) + { + if (requiredTogether == null) + return; + + foreach (object check in requiredTogether) + { + List requiredCheck = ((IList)check).Cast().ToList(); + List found = new List(); + foreach (string field in requiredCheck) + if (param.Contains(field)) + found.Add(true); + else + found.Add(false); + + if (found.Contains(true) && found.Contains(false)) + { + string msg = String.Format("parameters are required together: {0}", String.Join(", ", requiredCheck)); + FailJson(FormatOptionsContext(msg)); + } + } + } + + private void CheckRequiredOneOf(IDictionary param, IList requiredOneOf) + { + if (requiredOneOf == null) + return; + + foreach (object check in requiredOneOf) + { + List requiredCheck = ((IList)check).Cast().ToList(); + int count = 0; + foreach (string field in requiredCheck) + if (param.Contains(field)) + count++; + + if (count == 0) + { + string msg = String.Format("one of the following is required: {0}", String.Join(", ", requiredCheck)); + FailJson(FormatOptionsContext(msg)); + } + } + } + + private void CheckRequiredIf(IDictionary param, IList requiredIf) + { + if (requiredIf == null) + return; + + foreach (object check in requiredIf) + { + IList requiredCheck = (IList)check; + List missing = new List(); + List missingFields = new List(); + int maxMissingCount = 1; + bool oneRequired = false; + + if (requiredCheck.Count < 3 && requiredCheck.Count < 4) + FailJson(String.Format("internal error: invalid required_if value count of {0}, expecting 3 or 4 entries", requiredCheck.Count)); + else if (requiredCheck.Count == 4) + oneRequired = (bool)requiredCheck[3]; + + string key = (string)requiredCheck[0]; + object val = requiredCheck[1]; + IList requirements = (IList)requiredCheck[2]; + + if (ParseStr(param[key]) != ParseStr(val)) + continue; + + string term = "all"; + if (oneRequired) + { + maxMissingCount = requirements.Count; + term = "any"; + } + + foreach (string required in requirements.Cast()) + if (!param.Contains(required)) + missing.Add(required); + + if (missing.Count >= maxMissingCount) + { + string msg = String.Format("{0} is {1} but {2} of the following are missing: {3}", + key, val.ToString(), term, String.Join(", ", missing)); + FailJson(FormatOptionsContext(msg)); + } + } + } + + private void CheckRequiredBy(IDictionary param, IDictionary requiredBy) + { + foreach (DictionaryEntry entry in requiredBy) + { + string key = (string)entry.Key; + if (!param.Contains(key)) + continue; + + List missing = new List(); + List requires = ParseList(entry.Value).Cast().ToList(); + foreach (string required in requires) + if (!param.Contains(required)) + missing.Add(required); + + if (missing.Count > 0) + { + string msg = String.Format("missing parameter(s) required by '{0}': {1}", key, String.Join(", ", missing)); + FailJson(FormatOptionsContext(msg)); + } + } + } + + private void CheckSubOption(IDictionary param, string key, IDictionary spec) + { + object value = param[key]; + + string type; + if (spec["type"].GetType() == typeof(string)) + type = (string)spec["type"]; + else + type = "delegate"; + + string elements = null; + Delegate typeConverter = null; + if (spec["elements"] != null && spec["elements"].GetType() == typeof(string)) + { + elements = (string)spec["elements"]; + typeConverter = optionTypes[elements]; + } + else if (spec["elements"] != null) + { + elements = "delegate"; + typeConverter = (Delegate)spec["elements"]; + } + + if (!(type == "dict" || (type == "list" && elements != null))) + // either not a dict, or list with the elements set, so continue + return; + else if (type == "list") + { + // cast each list element to the type specified + if (value == null) + return; + + List newValue = new List(); + foreach (object element in (List)value) + { + if (elements == "dict") + newValue.Add(ParseSubSpec(spec, element, key)); + else + { + try + { + object newElement = typeConverter.DynamicInvoke(element); + newValue.Add(newElement); + } + catch (Exception e) + { + string msg = String.Format("argument for list entry {0} is of type {1} and we were unable to convert to {2}: {3}", + key, element.GetType(), elements, e.Message); + FailJson(FormatOptionsContext(msg)); + } + } + } + + param[key] = newValue; + } + else + param[key] = ParseSubSpec(spec, value, key); + } + + private object ParseSubSpec(IDictionary spec, object value, string context) + { + bool applyDefaults = (bool)spec["apply_defaults"]; + + // set entry to an empty dict if apply_defaults is set + IDictionary optionsSpec = (IDictionary)spec["options"]; + if (applyDefaults && optionsSpec.Keys.Count > 0 && value == null) + value = new Dictionary(); + else if (optionsSpec.Keys.Count == 0 || value == null) + return value; + + optionsContext.Add(context); + Dictionary newValue = (Dictionary)ParseDict(value); + Dictionary aliases = GetAliases(spec, newValue); + SetNoLogValues(spec, newValue); + + List subLegalInputs = optionsSpec.Keys.Cast().ToList(); + subLegalInputs.AddRange(aliases.Keys.Cast().ToList()); + + CheckArguments(spec, newValue, subLegalInputs); + optionsContext.RemoveAt(optionsContext.Count - 1); + return newValue; + } + + private string GetFormattedResults(Dictionary result) + { + if (!result.ContainsKey("invocation")) + result["invocation"] = new Dictionary() { { "module_args", RemoveNoLogValues(Params, noLogValues) } }; + + if (warnings.Count > 0) + result["warnings"] = warnings; + + if (deprecations.Count > 0) + result["deprecations"] = deprecations; + + if (Diff.Count > 0 && DiffMode) + result["diff"] = Diff; + + return ToJson(result); + } + + private string FormatLogData(object data, int indentLevel) + { + if (data == null) + return "$null"; + + string msg = ""; + if (data is IList) + { + string newMsg = ""; + foreach (object value in (IList)data) + { + string entryValue = FormatLogData(value, indentLevel + 2); + newMsg += String.Format("\r\n{0}- {1}", new String(' ', indentLevel), entryValue); + } + msg += newMsg; + } + else if (data is IDictionary) + { + bool start = true; + foreach (DictionaryEntry entry in (IDictionary)data) + { + string newMsg = FormatLogData(entry.Value, indentLevel + 2); + if (!start) + msg += String.Format("\r\n{0}", new String(' ', indentLevel)); + msg += String.Format("{0}: {1}", (string)entry.Key, newMsg); + start = false; + } + } + else + msg = (string)RemoveNoLogValues(ParseStr(data), noLogValues); + + return msg; + } + + private object RemoveNoLogValues(object value, HashSet noLogStrings) + { + Queue> deferredRemovals = new Queue>(); + object newValue = RemoveValueConditions(value, noLogStrings, deferredRemovals); + + while (deferredRemovals.Count > 0) + { + Tuple data = deferredRemovals.Dequeue(); + object oldData = data.Item1; + object newData = data.Item2; + + if (oldData is IDictionary) + { + foreach (DictionaryEntry entry in (IDictionary)oldData) + { + object newElement = RemoveValueConditions(entry.Value, noLogStrings, deferredRemovals); + ((IDictionary)newData).Add((string)entry.Key, newElement); + } + } + else + { + foreach (object element in (IList)oldData) + { + object newElement = RemoveValueConditions(element, noLogStrings, deferredRemovals); + ((IList)newData).Add(newElement); + } + } + } + + return newValue; + } + + private object RemoveValueConditions(object value, HashSet noLogStrings, Queue> deferredRemovals) + { + if (value == null) + return value; + + Type valueType = value.GetType(); + HashSet numericTypes = new HashSet + { + typeof(byte), typeof(sbyte), typeof(short), typeof(ushort), typeof(int), typeof(uint), + typeof(long), typeof(ulong), typeof(decimal), typeof(double), typeof(float) + }; + + if (numericTypes.Contains(valueType) || valueType == typeof(bool)) + { + string valueString = ParseStr(value); + if (noLogStrings.Contains(valueString)) + return "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"; + foreach (string omitMe in noLogStrings) + if (valueString.Contains(omitMe)) + return "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"; + } + else if (valueType == typeof(DateTime)) + value = ((DateTime)value).ToString("o"); + else if (value is IList) + { + List newValue = new List(); + deferredRemovals.Enqueue(new Tuple((IList)value, newValue)); + value = newValue; + } + else if (value is IDictionary) + { + Hashtable newValue = new Hashtable(); + deferredRemovals.Enqueue(new Tuple((IDictionary)value, newValue)); + value = newValue; + } + else + { + string stringValue = value.ToString(); + if (noLogStrings.Contains(stringValue)) + return "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER"; + foreach (string omitMe in noLogStrings) + if (stringValue.Contains(omitMe)) + return (stringValue).Replace(omitMe, "********"); + value = stringValue; + } + return value; + } + + private void CleanupFiles(object s, EventArgs ev) + { + foreach (string path in cleanupFiles) + { + if (File.Exists(path)) + File.Delete(path); + else if (Directory.Exists(path)) + Directory.Delete(path, true); + } + cleanupFiles = new List(); + } + + private string FormatOptionsContext(string msg, string prefix = " ") + { + if (optionsContext.Count > 0) + msg += String.Format("{0}found in {1}", prefix, String.Join(" -> ", optionsContext)); + return msg; + } + + [DllImport("kernel32.dll")] + private static extern IntPtr GetConsoleWindow(); + + private static void ExitModule(int rc) + { + // When running in a Runspace Environment.Exit will kill the entire + // process which is not what we want, detect if we are in a + // Runspace and call a ScriptBlock with exit instead. + if (Runspace.DefaultRunspace != null) + ScriptBlock.Create("Set-Variable -Name LASTEXITCODE -Value $args[0] -Scope Global; exit $args[0]").Invoke(rc); + else + { + // Used for local debugging in Visual Studio + if (System.Diagnostics.Debugger.IsAttached) + { + Console.WriteLine("Press enter to continue..."); + Console.ReadLine(); + } + Environment.Exit(rc); + } + } + + private static void WriteLineModule(string line) + { + Console.WriteLine(line); + } + } +} diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.ModuleUtils.AddType.psm1 b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.ModuleUtils.AddType.psm1 new file mode 100644 index 000000000..673070263 --- /dev/null +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/module_utils/_Ansible.ModuleUtils.AddType.psm1 @@ -0,0 +1,397 @@ +# Copyright (c) 2018 Ansible Project +# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) + +Function Add-CSharpType { + <# + .SYNOPSIS + Compiles one or more C# scripts similar to Add-Type. This exposes + more configuration options that are useable within Ansible and it + also allows multiple C# sources to be compiled together. + + .PARAMETER References + [String[]] A collection of C# scripts to compile together. + + .PARAMETER IgnoreWarnings + [Switch] Whether to compile code that contains compiler warnings, by + default warnings will cause a compiler error. + + .PARAMETER PassThru + [Switch] Whether to return the loaded Assembly + + .PARAMETER AnsibleModule + [Ansible.Basic.AnsibleModule] used to derive the TempPath and Debug values. + TempPath is set to the Tmpdir property of the class + IncludeDebugInfo is set when the Ansible verbosity is >= 3 + + .PARAMETER TempPath + [String] The temporary directory in which the dynamic assembly is + compiled to. This file is deleted once compilation is complete. + Cannot be used when AnsibleModule is set. This is a no-op when + running on PSCore. + + .PARAMETER IncludeDebugInfo + [Switch] Whether to include debug information in the compiled + assembly. Cannot be used when AnsibleModule is set. This is a no-op + when running on PSCore. + + .PARAMETER CompileSymbols + [String[]] A list of symbols to be defined during compile time. These are + added to the existing symbols, 'CORECLR', 'WINDOWS', 'UNIX' that are set + conditionalls in this cmdlet. + + .NOTES + The following features were added to control the compiling options from the + code itself. + + * Predefined compiler SYMBOLS + + * CORECLR - Added when running on PowerShell Core. + * WINDOWS - Added when running on Windows. + * UNIX - Added when running on non-Windows. + * X86 - Added when running on a 32-bit process (Ansible 2.10+) + * AMD64 - Added when running on a 64-bit process (Ansible 2.10+) + + * Ignore compiler warnings inline with the following comment inline + + //NoWarn -Name [-CLR Core|Framework] + + * Specify custom assembly references inline + + //AssemblyReference -Name Dll.Location.dll [-CLR Core|Framework] + + # Added in Ansible 2.10 + //AssemblyReference -Type System.Type.Name [-CLR Core|Framework] + + * Create automatic type accelerators to simplify long namespace names (Ansible 2.9+) + + //TypeAccelerator -Name -TypeName + #> + param( + [Parameter(Mandatory = $true)][AllowEmptyCollection()][String[]]$References, + [Switch]$IgnoreWarnings, + [Switch]$PassThru, + [Parameter(Mandatory = $true, ParameterSetName = "Module")][Object]$AnsibleModule, + [Parameter(ParameterSetName = "Manual")][String]$TempPath = $env:TMP, + [Parameter(ParameterSetName = "Manual")][Switch]$IncludeDebugInfo, + [String[]]$CompileSymbols = @() + ) + if ($null -eq $References -or $References.Length -eq 0) { + return + } + + # define special symbols CORECLR, WINDOWS, UNIX if required + # the Is* variables are defined on PSCore, if absent we assume an + # older version of PowerShell under .NET Framework and Windows + $defined_symbols = [System.Collections.ArrayList]$CompileSymbols + + if ([System.IntPtr]::Size -eq 4) { + $defined_symbols.Add('X86') > $null + } + else { + $defined_symbols.Add('AMD64') > $null + } + + $is_coreclr = Get-Variable -Name IsCoreCLR -ErrorAction SilentlyContinue + if ($null -ne $is_coreclr) { + if ($is_coreclr.Value) { + $defined_symbols.Add("CORECLR") > $null + } + } + $is_windows = Get-Variable -Name IsWindows -ErrorAction SilentlyContinue + if ($null -ne $is_windows) { + if ($is_windows.Value) { + $defined_symbols.Add("WINDOWS") > $null + } + else { + $defined_symbols.Add("UNIX") > $null + } + } + else { + $defined_symbols.Add("WINDOWS") > $null + } + + # Store any TypeAccelerators shortcuts the util wants us to set + $type_accelerators = [System.Collections.Generic.List`1[Hashtable]]@() + + # pattern used to find referenced assemblies in the code + $assembly_pattern = [Regex]"//\s*AssemblyReference\s+-(?(Name)|(Type))\s+(?[\w.]*)(\s+-CLR\s+(?Core|Framework))?" + $no_warn_pattern = [Regex]"//\s*NoWarn\s+-Name\s+(?[\w\d]*)(\s+-CLR\s+(?Core|Framework))?" + $type_pattern = [Regex]"//\s*TypeAccelerator\s+-Name\s+(?[\w.]*)\s+-TypeName\s+(?[\w.]*)" + + # PSCore vs PSDesktop use different methods to compile the code, + # PSCore uses Roslyn and can compile the code purely in memory + # without touching the disk while PSDesktop uses CodeDom and csc.exe + # to compile the code. We branch out here and run each + # distribution's method to add our C# code. + if ($is_coreclr) { + # compile the code using Roslyn on PSCore + + # Include the default assemblies using the logic in Add-Type + # https://github.com/PowerShell/PowerShell/blob/master/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs + $assemblies = [System.Collections.Generic.HashSet`1[Microsoft.CodeAnalysis.MetadataReference]]@( + [Microsoft.CodeAnalysis.CompilationReference]::CreateFromFile(([System.Reflection.Assembly]::GetAssembly([PSObject])).Location) + ) + $netcore_app_ref_folder = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName([PSObject].Assembly.Location), "ref") + $lib_assembly_location = [System.IO.Path]::GetDirectoryName([object].Assembly.Location) + foreach ($file in [System.IO.Directory]::EnumerateFiles($netcore_app_ref_folder, "*.dll", [System.IO.SearchOption]::TopDirectoryOnly)) { + $assemblies.Add([Microsoft.CodeAnalysis.MetadataReference]::CreateFromFile($file)) > $null + } + + # loop through the references, parse as a SyntaxTree and get + # referenced assemblies + $ignore_warnings = New-Object -TypeName 'System.Collections.Generic.Dictionary`2[[String], [Microsoft.CodeAnalysis.ReportDiagnostic]]' + $parse_options = ([Microsoft.CodeAnalysis.CSharp.CSharpParseOptions]::Default).WithPreprocessorSymbols($defined_symbols) + $syntax_trees = [System.Collections.Generic.List`1[Microsoft.CodeAnalysis.SyntaxTree]]@() + foreach ($reference in $References) { + # scan through code and add any assemblies that match + # //AssemblyReference -Name ... [-CLR Core] + # //NoWarn -Name ... [-CLR Core] + # //TypeAccelerator -Name ... -TypeName ... + $assembly_matches = $assembly_pattern.Matches($reference) + foreach ($match in $assembly_matches) { + $clr = $match.Groups["CLR"].Value + if ($clr -and $clr -ne "Core") { + continue + } + + $parameter_type = $match.Groups["Parameter"].Value + $assembly_path = $match.Groups["Name"].Value + if ($parameter_type -eq "Type") { + $assembly_path = ([Type]$assembly_path).Assembly.Location + } + else { + if (-not ([System.IO.Path]::IsPathRooted($assembly_path))) { + $assembly_path = Join-Path -Path $lib_assembly_location -ChildPath $assembly_path + } + } + $assemblies.Add([Microsoft.CodeAnalysis.MetadataReference]::CreateFromFile($assembly_path)) > $null + } + $warn_matches = $no_warn_pattern.Matches($reference) + foreach ($match in $warn_matches) { + $clr = $match.Groups["CLR"].Value + if ($clr -and $clr -ne "Core") { + continue + } + $ignore_warnings.Add($match.Groups["Name"], [Microsoft.CodeAnalysis.ReportDiagnostic]::Suppress) + } + $syntax_trees.Add([Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree]::ParseText($reference, $parse_options)) > $null + + $type_matches = $type_pattern.Matches($reference) + foreach ($match in $type_matches) { + $type_accelerators.Add(@{Name = $match.Groups["Name"].Value; TypeName = $match.Groups["TypeName"].Value }) + } + } + + # Release seems to contain the correct line numbers compared to + # debug,may need to keep a closer eye on this in the future + $compiler_options = (New-Object -TypeName Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions -ArgumentList @( + [Microsoft.CodeAnalysis.OutputKind]::DynamicallyLinkedLibrary + )).WithOptimizationLevel([Microsoft.CodeAnalysis.OptimizationLevel]::Release) + + # set warnings to error out if IgnoreWarnings is not set + if (-not $IgnoreWarnings.IsPresent) { + $compiler_options = $compiler_options.WithGeneralDiagnosticOption([Microsoft.CodeAnalysis.ReportDiagnostic]::Error) + $compiler_options = $compiler_options.WithSpecificDiagnosticOptions($ignore_warnings) + } + + # create compilation object + $compilation = [Microsoft.CodeAnalysis.CSharp.CSharpCompilation]::Create( + [System.Guid]::NewGuid().ToString(), + $syntax_trees, + $assemblies, + $compiler_options + ) + + # Load the compiled code and pdb info, we do this so we can + # include line number in a stracktrace + $code_ms = New-Object -TypeName System.IO.MemoryStream + $pdb_ms = New-Object -TypeName System.IO.MemoryStream + try { + $emit_result = $compilation.Emit($code_ms, $pdb_ms) + if (-not $emit_result.Success) { + $errors = [System.Collections.ArrayList]@() + + foreach ($e in $emit_result.Diagnostics) { + # builds the error msg, based on logic in Add-Type + # https://github.com/PowerShell/PowerShell/blob/master/src/Microsoft.PowerShell.Commands.Utility/commands/utility/AddType.cs#L1239 + if ($null -eq $e.Location.SourceTree) { + $errors.Add($e.ToString()) > $null + continue + } + + $cancel_token = New-Object -TypeName System.Threading.CancellationToken -ArgumentList $false + $text_lines = $e.Location.SourceTree.GetText($cancel_token).Lines + $line_span = $e.Location.GetLineSpan() + + $diagnostic_message = $e.ToString() + $error_line_string = $text_lines[$line_span.StartLinePosition.Line].ToString() + $error_position = $line_span.StartLinePosition.Character + + $sb = New-Object -TypeName System.Text.StringBuilder -ArgumentList ($diagnostic_message.Length + $error_line_string.Length * 2 + 4) + $sb.AppendLine($diagnostic_message) + $sb.AppendLine($error_line_string) + + for ($i = 0; $i -lt $error_line_string.Length; $i++) { + if ([System.Char]::IsWhiteSpace($error_line_string[$i])) { + continue + } + $sb.Append($error_line_string, 0, $i) + $sb.Append(' ', [Math]::Max(0, $error_position - $i)) + $sb.Append("^") + break + } + + $errors.Add($sb.ToString()) > $null + } + + throw [InvalidOperationException]"Failed to compile C# code:`r`n$($errors -join "`r`n")" + } + + $code_ms.Seek(0, [System.IO.SeekOrigin]::Begin) > $null + $pdb_ms.Seek(0, [System.IO.SeekOrigin]::Begin) > $null + $compiled_assembly = [System.Runtime.Loader.AssemblyLoadContext]::Default.LoadFromStream($code_ms, $pdb_ms) + } + finally { + $code_ms.Close() + $pdb_ms.Close() + } + } + else { + # compile the code using CodeDom on PSDesktop + + # configure compile options based on input + if ($PSCmdlet.ParameterSetName -eq "Module") { + $temp_path = $AnsibleModule.Tmpdir + $include_debug = $AnsibleModule.Verbosity -ge 3 + } + else { + $temp_path = $TempPath + $include_debug = $IncludeDebugInfo.IsPresent + } + $compiler_options = [System.Collections.ArrayList]@("/optimize") + if ($defined_symbols.Count -gt 0) { + $compiler_options.Add("/define:" + ([String]::Join(";", $defined_symbols.ToArray()))) > $null + } + + $compile_parameters = New-Object -TypeName System.CodeDom.Compiler.CompilerParameters + $compile_parameters.GenerateExecutable = $false + $compile_parameters.GenerateInMemory = $true + $compile_parameters.TreatWarningsAsErrors = (-not $IgnoreWarnings.IsPresent) + $compile_parameters.IncludeDebugInformation = $include_debug + $compile_parameters.TempFiles = (New-Object -TypeName System.CodeDom.Compiler.TempFileCollection -ArgumentList $temp_path, $false) + + # Add-Type automatically references System.dll, System.Core.dll, + # and System.Management.Automation.dll which we replicate here + $assemblies = [System.Collections.Generic.HashSet`1[String]]@( + "System.dll", + "System.Core.dll", + ([System.Reflection.Assembly]::GetAssembly([PSObject])).Location + ) + + # create a code snippet for each reference and check if we need + # to reference any extra assemblies + $ignore_warnings = [System.Collections.ArrayList]@() + $compile_units = [System.Collections.Generic.List`1[System.CodeDom.CodeSnippetCompileUnit]]@() + foreach ($reference in $References) { + # scan through code and add any assemblies that match + # //AssemblyReference -Name ... [-CLR Framework] + # //NoWarn -Name ... [-CLR Framework] + # //TypeAccelerator -Name ... -TypeName ... + $assembly_matches = $assembly_pattern.Matches($reference) + foreach ($match in $assembly_matches) { + $clr = $match.Groups["CLR"].Value + if ($clr -and $clr -ne "Framework") { + continue + } + + $parameter_type = $match.Groups["Parameter"].Value + $assembly_path = $match.Groups["Name"].Value + if ($parameter_type -eq "Type") { + $assembly_path = ([Type]$assembly_path).Assembly.Location + } + $assemblies.Add($assembly_path) > $null + } + $warn_matches = $no_warn_pattern.Matches($reference) + foreach ($match in $warn_matches) { + $clr = $match.Groups["CLR"].Value + if ($clr -and $clr -ne "Framework") { + continue + } + $warning_id = $match.Groups["Name"].Value + # /nowarn should only contain the numeric part + if ($warning_id.StartsWith("CS")) { + $warning_id = $warning_id.Substring(2) + } + $ignore_warnings.Add($warning_id) > $null + } + $compile_units.Add((New-Object -TypeName System.CodeDom.CodeSnippetCompileUnit -ArgumentList $reference)) > $null + + $type_matches = $type_pattern.Matches($reference) + foreach ($match in $type_matches) { + $type_accelerators.Add(@{Name = $match.Groups["Name"].Value; TypeName = $match.Groups["TypeName"].Value }) + } + } + if ($ignore_warnings.Count -gt 0) { + $compiler_options.Add("/nowarn:" + ([String]::Join(",", $ignore_warnings.ToArray()))) > $null + } + $compile_parameters.ReferencedAssemblies.AddRange($assemblies) + $compile_parameters.CompilerOptions = [String]::Join(" ", $compiler_options.ToArray()) + + # compile the code together and check for errors + $provider = New-Object -TypeName Microsoft.CSharp.CSharpCodeProvider + + # This calls csc.exe which can take compiler options from environment variables. Currently these env vars + # are known to have problems so they are unset: + # LIB - additional library paths will fail the compilation if they are invalid + $originalEnv = @{} + try { + 'LIB' | ForEach-Object -Process { + $value = Get-Item -LiteralPath "Env:\$_" -ErrorAction SilentlyContinue + if ($value) { + $originalEnv[$_] = $value + Remove-Item -LiteralPath "Env:\$_" + } + } + + $compile = $provider.CompileAssemblyFromDom($compile_parameters, $compile_units) + } + finally { + foreach ($kvp in $originalEnv.GetEnumerator()) { + [System.Environment]::SetEnvironmentVariable($kvp.Key, $kvp.Value, "Process") + } + } + + if ($compile.Errors.HasErrors) { + $msg = "Failed to compile C# code: " + foreach ($e in $compile.Errors) { + $msg += "`r`n" + $e.ToString() + } + throw [InvalidOperationException]$msg + } + $compiled_assembly = $compile.CompiledAssembly + } + + $type_accelerator = [PSObject].Assembly.GetType("System.Management.Automation.TypeAccelerators") + foreach ($accelerator in $type_accelerators) { + $type_name = $accelerator.TypeName + $found = $false + + foreach ($assembly_type in $compiled_assembly.GetTypes()) { + if ($assembly_type.Name -eq $type_name) { + $type_accelerator::Add($accelerator.Name, $assembly_type) + $found = $true + break + } + } + if (-not $found) { + throw "Failed to find compiled class '$type_name' for custom TypeAccelerator." + } + } + + # return the compiled assembly if PassThru is set. + if ($PassThru) { + return $compiled_assembly + } +} + +Export-ModuleMember -Function Add-CSharpType diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/shell_plugins/pwsh.py b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/shell_plugins/pwsh.py index 468c54069..9b1601046 100644 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/shell_plugins/pwsh.py +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_sqlserver_test_plugins/shell_plugins/pwsh.py @@ -59,10 +59,15 @@ import re import shlex import pkgutil import xml.etree.ElementTree as ET -import ntpath + +from packaging import version from ansible.module_utils._text import to_bytes, to_text from ansible.plugins.shell import ShellBase +from ansible.release import __version__ as ansible_version +from ansible.utils.display import Display + +display = Display() _common_args = ['pwsh', '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Unrestricted'] @@ -223,18 +228,12 @@ class ShellModule(ShellBase): def build_module_command(self, env_string, shebang, cmd, arg_path=None): bootstrap_wrapper = pkgutil.get_data("ansible.executor.powershell", "bootstrap_wrapper.ps1") - # pipelining bypass - if cmd == '': - return self._encode_script(script=bootstrap_wrapper, strict_mode=False, preserve_rc=False) - - # non-pipelining - - cmd_parts = shlex.split(cmd, posix=False) - cmd_parts = list(map(to_text, cmd_parts)) - if shebang and shebang.lower() == '#!powershell': - if not self._unquote(cmd_parts[0]).lower().endswith('.ps1'): - # we're running a module via the bootstrap wrapper - cmd_parts[0] = '"%s.ps1"' % self._unquote(cmd_parts[0]) + # TODO: remove when support for ansible-core <2.13 is dropped + ver = version.parse(ansible_version) + cutoff = version.parse('2.13') + info = "ansible_version (parsed) [<2.13]: %s (%s) [%r]" % (ansible_version, ver, (ver < cutoff)) + display.vvv(info) + if ver < cutoff: # HACK begin dirty, dirty hack # we need to override the built-in Ansible.Basic module util # to one that will work on non-Windows platforms. @@ -246,8 +245,8 @@ class ShellModule(ShellBase): # before it made it to the remote host. The reason we can't just embed it in commands as strings is because # it will be too big. local_mu = os.path.join(os.path.dirname(__file__), '..', 'module_utils') - ansible_basic_cs = os.path.join(local_mu, 'Ansible.Basic.cs') - addtype_ps = os.path.join(local_mu, 'Ansible.ModuleUtils.AddType.psm1') + ansible_basic_cs = os.path.join(local_mu, '_Ansible.Basic.cs') + addtype_ps = os.path.join(local_mu, '_Ansible.ModuleUtils.AddType.psm1') wrapper_hacked = ''' &chcp.com 65001 > $null $exec_wrapper_str = $input | Out-String @@ -286,6 +285,21 @@ class ShellModule(ShellBase): &$exec_wrapper ''' % (ansible_basic_cs, addtype_ps) bootstrap_wrapper = wrapper_hacked + # end hack for ansible-core < 2.13 + + # pipelining bypass + if cmd == '': + return self._encode_script(script=bootstrap_wrapper, strict_mode=False, preserve_rc=False) + + # non-pipelining + + cmd_parts = shlex.split(cmd, posix=False) + cmd_parts = list(map(to_text, cmd_parts)) + if shebang and shebang.lower() == '#!powershell': + if not self._unquote(cmd_parts[0]).lower().endswith('.ps1'): + # we're running a module via the bootstrap wrapper + cmd_parts[0] = '"%s.ps1"' % self._unquote(cmd_parts[0]) + wrapper_cmd = "cat " + cmd_parts[0] + " | " + self._encode_script(script=bootstrap_wrapper, strict_mode=False, preserve_rc=False) return wrapper_cmd elif shebang and shebang.startswith('#!'): diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_win_sqlserver/tasks/main.yml b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_win_sqlserver/tasks/main.yml index acc1dbeb4..0928ecc1c 100644 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_win_sqlserver/tasks/main.yml +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/setup_win_sqlserver/tasks/main.yml @@ -2,7 +2,6 @@ - name: Install Powershell modules ansible.windows.win_shell: | {{ item }} - no_log: "{{ ansible_verbosity | int < 3 }}" loop: - - "{{ dbatools_install_cmd }}" - "{{ dbops_install_cmd }}" + - "{{ dbatools_install_cmd }}" diff --git a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/win_ag_replica/tasks/main.yml b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/win_ag_replica/tasks/main.yml index 8a8990789..feb3acb55 100644 --- a/ansible_collections/lowlydba/sqlserver/tests/integration/targets/win_ag_replica/tasks/main.yml +++ b/ansible_collections/lowlydba/sqlserver/tests/integration/targets/win_ag_replica/tasks/main.yml @@ -56,6 +56,10 @@ lowlydba.sqlserver.availability_group: register: ag + - name: Set ag SqlInstance fact + set_fact: + ag_sql_instance: "{{ ag.data.SqlInstance }}" + - name: Set replica lowlydba.sqlserver.ag_replica: session_timeout: 20 @@ -72,7 +76,6 @@ - result.data.AvailabilityMode == availability_mode - result.data.SessionTimeout == 20 - result.data.FailoverMode == failover_mode - - result.data.EndpointUrl == "TCP://{{ ag.data.SqlInstance }}:5022" - result is changed always: -- cgit v1.2.3