diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-05 16:18:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-05 16:18:34 +0000 |
commit | 3667197efb7b18ec842efd504785965911f8ac4b (patch) | |
tree | 0b986a4bc6879d080b100666a97cdabbc9ca1f28 /ansible_collections/azure | |
parent | Adding upstream version 9.5.1+dfsg. (diff) | |
download | ansible-1f02d92b7a8d732f4e9bbdeb50c68dd718d53d00.tar.xz ansible-1f02d92b7a8d732f4e9bbdeb50c68dd718d53d00.zip |
Adding upstream version 10.0.0+dfsg.upstream/10.0.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/azure')
206 files changed, 11721 insertions, 4615 deletions
diff --git a/ansible_collections/azure/azcollection/.gitignore b/ansible_collections/azure/azcollection/.gitignore index a5e318764..f92aa6737 100644 --- a/ansible_collections/azure/azcollection/.gitignore +++ b/ansible_collections/azure/azcollection/.gitignore @@ -7,3 +7,4 @@ venv* .vscode ansible_collections/ .idea/ +tests/integration/inventory diff --git a/ansible_collections/azure/azcollection/.idea/.gitignore b/ansible_collections/azure/azcollection/.idea/.gitignore deleted file mode 100644 index 1c2fda565..000000000 --- a/ansible_collections/azure/azcollection/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/ansible_collections/azure/azcollection/.idea/azcollection.iml b/ansible_collections/azure/azcollection/.idea/azcollection.iml deleted file mode 100644 index 6db416ffe..000000000 --- a/ansible_collections/azure/azcollection/.idea/azcollection.iml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<module type="PYTHON_MODULE" version="4">
- <component name="NewModuleRootManager">
- <content url="file://$MODULE_DIR$" />
- <orderEntry type="jdk" jdkName="Python 3.10.12 WSL (Ubuntu-22.04): (/home/eric/workspace/ansible-workspace/mymodule/test/bin/python3)" jdkType="Python SDK" />
- <orderEntry type="sourceFolder" forTests="false" />
- </component>
- <component name="PyDocumentationSettings">
- <option name="format" value="PLAIN" />
- <option name="myDocStringFormat" value="Plain" />
- </component>
-</module>
\ No newline at end of file diff --git a/ansible_collections/azure/azcollection/.idea/inspectionProfiles/profiles_settings.xml b/ansible_collections/azure/azcollection/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2da2..000000000 --- a/ansible_collections/azure/azcollection/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ -<component name="InspectionProjectProfileManager"> - <settings> - <option name="USE_PROJECT_PROFILE" value="false" /> - <version value="1.0" /> - </settings> -</component>
\ No newline at end of file diff --git a/ansible_collections/azure/azcollection/.idea/misc.xml b/ansible_collections/azure/azcollection/.idea/misc.xml deleted file mode 100644 index ecadf7f30..000000000 --- a/ansible_collections/azure/azcollection/.idea/misc.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="Black">
- <option name="sdkName" value="Python 3.10.12 WSL (Ubuntu-22.04): (/home/eric/workspace/ansible-workspace/mymodule/test/bin/python3)" />
- </component>
- <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10.12 WSL (Ubuntu-22.04): (/home/eric/workspace/ansible-workspace/mymodule/test/bin/python3)" project-jdk-type="Python SDK" />
-</project>
\ No newline at end of file diff --git a/ansible_collections/azure/azcollection/.idea/modules.xml b/ansible_collections/azure/azcollection/.idea/modules.xml deleted file mode 100644 index 2701c413f..000000000 --- a/ansible_collections/azure/azcollection/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="ProjectModuleManager">
- <modules>
- <module fileurl="file://$PROJECT_DIR$/.idea/azcollection.iml" filepath="$PROJECT_DIR$/.idea/azcollection.iml" />
- </modules>
- </component>
-</project>
\ No newline at end of file diff --git a/ansible_collections/azure/azcollection/.idea/vcs.xml b/ansible_collections/azure/azcollection/.idea/vcs.xml deleted file mode 100644 index c8397c94c..000000000 --- a/ansible_collections/azure/azcollection/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="VcsDirectoryMappings">
- <mapping directory="" vcs="Git" />
- </component>
-</project>
\ No newline at end of file diff --git a/ansible_collections/azure/azcollection/.idea/workspace.xml b/ansible_collections/azure/azcollection/.idea/workspace.xml deleted file mode 100644 index 88ec9a9b1..000000000 --- a/ansible_collections/azure/azcollection/.idea/workspace.xml +++ /dev/null @@ -1,138 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="AutoImportSettings">
- <option name="autoReloadType" value="SELECTIVE" />
- </component>
- <component name="ChangeListManager">
- <list default="true" id="d047ab49-1c87-4a80-9a8a-6e10b8f617c7" name="Changes" comment="deprecate tenant ID" />
- <option name="SHOW_DIALOG" value="false" />
- <option name="HIGHLIGHT_CONFLICTS" value="true" />
- <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
- <option name="LAST_RESOLUTION" value="IGNORE" />
- </component>
- <component name="Git.Settings">
- <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
- </component>
- <component name="MarkdownSettingsMigration">
- <option name="stateVersion" value="1" />
- </component>
- <component name="ProjectColorInfo">{ - "associatedIndex": 3 -}</component>
- <component name="ProjectId" id="2V04ePwIacqirqMx6z2ILJcwwz8" />
- <component name="ProjectViewState">
- <option name="hideEmptyMiddlePackages" value="true" />
- <option name="showLibraryContents" value="true" />
- </component>
- <component name="PropertiesComponent">{ - "keyToString": { - "RunOnceActivity.OpenProjectViewOnStart": "true", - "RunOnceActivity.ShowReadmeOnStart": "true", - "WebServerToolWindowFactoryState": "false", - "git-widget-placeholder": "f/msgraph__beta", - "last_opened_file_path": "//wsl$/Ubuntu-22.04/home/eric/workspace/ansible-workspace/azcollection", - "node.js.detected.package.eslint": "true", - "node.js.detected.package.tslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "node.js.selected.package.tslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable", - "vue.rearranger.settings.migration": "true" - } -}</component>
- <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
- <component name="TaskManager">
- <task active="true" id="Default" summary="Default task">
- <changelist id="d047ab49-1c87-4a80-9a8a-6e10b8f617c7" name="Changes" comment="" />
- <created>1693959760639</created>
- <option name="number" value="Default" />
- <option name="presentableId" value="Default" />
- <updated>1693959760639</updated>
- <workItem from="1693959762094" duration="3039000" />
- <workItem from="1693972601745" duration="6259000" />
- <workItem from="1694156355409" duration="318000" />
- <workItem from="1695017100314" duration="636000" />
- <workItem from="1697608879446" duration="1750000" />
- <workItem from="1697612810177" duration="444000" />
- <workItem from="1697697857011" duration="781000" />
- <workItem from="1698046408261" duration="2057000" />
- <workItem from="1698115035079" duration="743000" />
- </task>
- <task id="LOCAL-00001" summary="msgraph client">
- <option name="closed" value="true" />
- <created>1693977495938</created>
- <option name="number" value="00001" />
- <option name="presentableId" value="LOCAL-00001" />
- <option name="project" value="LOCAL" />
- <updated>1693977495938</updated>
- </task>
- <task id="LOCAL-00002" summary="msgraph client">
- <option name="closed" value="true" />
- <created>1693977569076</created>
- <option name="number" value="00002" />
- <option name="presentableId" value="LOCAL-00002" />
- <option name="project" value="LOCAL" />
- <updated>1693977569076</updated>
- </task>
- <task id="LOCAL-00003" summary="migrate account API from graphrbac to msgraph">
- <option name="closed" value="true" />
- <created>1693977622517</created>
- <option name="number" value="00003" />
- <option name="presentableId" value="LOCAL-00003" />
- <option name="project" value="LOCAL" />
- <updated>1693977622517</updated>
- </task>
- <task id="LOCAL-00004" summary="fix sanity">
- <option name="closed" value="true" />
- <created>1695017609087</created>
- <option name="number" value="00004" />
- <option name="presentableId" value="LOCAL-00004" />
- <option name="project" value="LOCAL" />
- <updated>1695017609087</updated>
- </task>
- <task id="LOCAL-00005" summary="fix sanity">
- <option name="closed" value="true" />
- <created>1697611839381</created>
- <option name="number" value="00005" />
- <option name="presentableId" value="LOCAL-00005" />
- <option name="project" value="LOCAL" />
- <updated>1697611839381</updated>
- </task>
- <task id="LOCAL-00006" summary="fix sanity">
- <option name="closed" value="true" />
- <created>1697613231431</created>
- <option name="number" value="00006" />
- <option name="presentableId" value="LOCAL-00006" />
- <option name="project" value="LOCAL" />
- <updated>1697613231431</updated>
- </task>
- <task id="LOCAL-00007" summary="deprecate tenant ID">
- <option name="closed" value="true" />
- <created>1697698300998</created>
- <option name="number" value="00007" />
- <option name="presentableId" value="LOCAL-00007" />
- <option name="project" value="LOCAL" />
- <updated>1697698300998</updated>
- </task>
- <task id="LOCAL-00008" summary="deprecate tenant ID">
- <option name="closed" value="true" />
- <created>1698048324225</created>
- <option name="number" value="00008" />
- <option name="presentableId" value="LOCAL-00008" />
- <option name="project" value="LOCAL" />
- <updated>1698048324225</updated>
- </task>
- <option name="localTasksCounter" value="9" />
- <servers />
- </component>
- <component name="TypeScriptGeneratedFilesManager">
- <option name="version" value="3" />
- </component>
- <component name="VcsManagerConfiguration">
- <MESSAGE value="msgraph client" />
- <MESSAGE value="migrate account API from graphrbac to msgraph" />
- <MESSAGE value="fix sanity" />
- <MESSAGE value="deprecate tenant ID" />
- <option name="LAST_COMMIT_MESSAGE" value="deprecate tenant ID" />
- </component>
-</project>
\ No newline at end of file diff --git a/ansible_collections/azure/azcollection/CHANGELOG.md b/ansible_collections/azure/azcollection/CHANGELOG.md index e25da8d72..f271fc377 100644 --- a/ansible_collections/azure/azcollection/CHANGELOG.md +++ b/ansible_collections/azure/azcollection/CHANGELOG.md @@ -1,5 +1,212 @@ # Change Log +## v2.3.0 (2024-03-27) + +### NEW MODULES + - azure_rm_akscredentials_info: Support to obtain Azure Kubernetes Service Credentials ([#1484](https://github.com/ansible-collections/azure/pull/1484)) + +### FEATURE ENHANCEMENT + - sanity-requirements-azure.txt: + - Bump cryptography from 41.0.6 to 42.0.2 ([#1450](https://github.com/ansible-collections/azure/pull/1450)) + - Bump cryptography from 42.0.2 to 42.0.4 ([#1458](https://github.com/ansible-collections/azure/pull/1458)) + - azure_rm_networkinterface_info: Return the subnet ID ([#1462](https://github.com/ansible-collections/azure/pull/1462)) + - azure_rm_appgateway: Add support for `port` and `match` in `probes` ([#1470](https://github.com/ansible-collections/azure/pull/1470)) + - azure_rm_common.py: + - Add support for import new version `azure-mgmt-recoveryservicesbackup` modules ([#1469](https://github.com/ansible-collections/azure/pull/1469)) + - Add support for `disable_instance_discovery` ([#1442](https://github.com/ansible-collections/azure/pull/1442)) + - Respect `AZURE_CLIENT_ID`, `ANSIBLE_AZURE_AUTH_SOURCE` on inventory plugin ([#713](https://github.com/ansible-collections/azure/pull/713)) + - azure_rm_aksversion_info: Add support for `allow_preview` ([#1456](https://github.com/ansible-collections/azure/pull/1456)) + - azure_rm_adgroup: Add Support for `description` ([#1492](https://github.com/ansible-collections/azure/pull/1492)) + - azure_rm_adgroup_info: Add support for `description` ([#1492](https://github.com/ansible-collections/azure/pull/1492)) + - azure_rm_wbapp: Support to create Web App with Java11/Java17/Java21 ([#1495](https://github.com/ansible-collections/azure/pull/1495)) + - azure_rm_adapplication: Add support for `spa_redirect_urls` and `public_client_redirect_urls` ([#1494](https://github.com/ansible-collections/azure/pull/1494)) + - azure_rm_adapplication_info: Add support for `spa_redirect_urls` and `public_client_redirect_urls` ([#1494](https://github.com/ansible-collections/azure/pull/1494)) + - azure_rm_galleryimage: Add support for `architecture` ([#1493](https://github.com/ansible-collections/azure/pull/1493)) + - azure_rm_keyvaultsecret: Support recover/purge deleted secrets ([#1489](https://github.com/ansible-collections/azure/pull/1489)) + - azure_rm_keyvaultsecret_info: Support recover/purge deleted secrets ([#1489](https://github.com/ansible-collections/azure/pull/1489)) + - azure_rm_recoveryservicesvault_info: Support listing the vaults in same resource group ([#1487](https://github.com/ansible-collections/azure/pull/1487)) + - azure_rm_resource_info: Add support for `tags` ([#1498](https://github.com/ansible-collections/azure/pull/1498)) + - azure_rm_aduser: Add support for `company_name` ([#1504](https://github.com/ansible-collections/azure/pull/1504)) + - azure_rm_aduser_info: Add support for `company_name` ([#1504](https://github.com/ansible-collections/azure/pull/1504)) + - azure_rm_aks: Support manage pod identities in managed Kubernetes cluster ([#1497](https://github.com/ansible-collections/azure/pull/1497)) + - azure_rm_adserviceprincipal_info: Fix listing all service principals ([#1482](https://github.com/ansible-collections/azure/pull/1482)) + - azure_rm_virtualmachie: Add support for swap OS disk ([#1435](https://github.com/ansible-collections/azure/pull/1435)) + +### BUG FIXING + - azure_rm_adgroup: Fix unsupported header in azure_rm_adgroup ([#1467](https://github.com/ansible-collections/azure/pull/1467)) + - azure_rm_keyvaultkey_info: Typos fix ([#1468](https://github.com/ansible-collections/azure/pull/1468)) + - azure_rm_sqlmanagedinstance: Typos fix ([#1468](https://github.com/ansible-collections/azure/pull/1468)) + - azure_rm_sqlmanagedinstance_info: Typos fix ([#1468](https://github.com/ansible-collections/azure/pull/1468)) + - azure_rm_virtualmachine: Typos fix ([#1468](https://github.com/ansible-collections/azure/pull/1468)) + - ../azure_rm_storageaccount/tasks/main.yml: Removing leftover storage account from test ([#1449](https://github.com/ansible-collections/azure/pull/1449)) + - azure_rm_aduser_info: Parse paginated replies for listing all users/groups ([#1448](https://github.com/ansible-collections/azure/pull/1448)) + - azure_rm_adgroup_info: Parse paginated replies for listing all users/groups ([#1448](https://github.com/ansible-collections/azure/pull/1448)) + - azure_rm.py: Allow for template expressions in some parameters ([#1446](https://github.com/ansible-collections/azure/pull/1446)) + - azure_rm_galleryimageversion_info: Check the return value ([#1436](https://github.com/ansible-collections/azure/pull/1436)) + - azure_rm_servicebus_info: Fixed return value format error ([#1503](https://github.com/ansible-collections/azure/pull/1503)) + - azure_rm_appgateway: Ensure `enable_http2` works when targeting existing Application Gateways ([#1439](https://github.com/ansible-collections/azure/pull/1439)) + - azure_rm_datalakestore: Disable testings due to the Azure Data Lake Store Gen1 retired ([#1501](https://github.com/ansible-collections/azure/pull/1501)) + - azure_rm_datalakestore_info: Disable testings due to the Azure Data Lake Store Gen1 retired ([#1501](https://github.com/ansible-collections/azure/pull/1501)) + - azure_rm_gallery_info: Detects the return value and returns None if the return value is empty ([#1483](https://github.com/ansible-collections/azure/pull/1483)) + - azure_rm_account_info: Change the default value of `is_ad_resource` to True ([#1510](https://github.com/ansible-collections/azure/pull/1510)) + + +## v2.2.0 (2024-02-04) + +### NEW MODULES + - azure_rm_publicipprefix ([#1403](https://github.com/ansible-collections/azure/pull/1403)) + - azure_rm_publicipprefix_info ([#1403](https://github.com/ansible-collections/azure/pull/1403)) + - azure_rm_sshpublickey ([#1190](https://github.com/ansible-collections/azure/pull/1190)) + - azure_rm_sshpublickey_info ([#1190](https://github.com/ansible-collections/azure/pull/1190)) + - azure_rm_postgresqlflexibleserver ([1192](https://github.com/ansible-collections/azure/pull/1192)) + - azure_rm_postgresqlflexibleserver_info ([1192](https://github.com/ansible-collections/azure/pull/1192)) + - azure_rm_postgresqlflexibleconfiguration_info ([1192](https://github.com/ansible-collections/azure/pull/1192)) + - azure_rm_postgresqlflexibledatabase ([1192](https://github.com/ansible-collections/azure/pull/1192)) + - azure_rm_postgresqlflexibledatabase_info ([1192](https://github.com/ansible-collections/azure/pull/1192)) + - azure_rm_postgresqlflexiblefirewallrule ([1192](https://github.com/ansible-collections/azure/pull/1192)) + - azure_rm_postgresqlflexiblefirewallrule_info ([1192](https://github.com/ansible-collections/azure/pull/1192)) + +### FEATURE ENHANCEMENT + - azure_rm_adapplication: Add support for `sign_in_audience` ([#1401](https://github.com/ansible-collections/azure/pull/1401)) + - plugins/inventory/azure_rm.py: + - Add support for export `lincense_type` ([#1411](https://github.com/ansible-collections/azure/pull/1411)) + - Set `andible_host` to Public IP Address, use Private IP Address if not exist ([#1406](https://github.com/ansible-collections/azure/pull/1406)) + - Add support for export `subnet` ([#1422](https://github.com/ansible-collections/azure/pull/1422)) + - azure_rm_virtualmachine: Add support for `additional_capabilities` ([#1399](https://github.com/ansible-collections/azure/pull/1399)) + - azure_rm_storageaccount: Add support for `enable_nfs_v3` ([#1346](https://github.com/ansible-collections/azure/pull/1346)) + - azure_rm_subnet: Add `Microsoft.ContainerService/managedClusters` to subnet delegations ([#1414](https://github.com/ansible-collections/azure/pull/1414)) + - azure_rm_adapplication_info: + - Searching by tenant returns all AD applications ([#1420](https://github.com/ansible-collections/azure/pull/1420)) + - Enhance search for application by `app_display_name` ([#1420](https://github.com/ansible-collections/azure/pull/1420)) + - azure_rm_appgateway: Add support `tags` ([#1373](https://github.com/ansible-collections/azure/pull/1373)) + +### BUG FIXING + - azure_rm_common.py: + - Fix missing `client_id` in payload error when using only username/password ([#1409](https://github.com/ansible-collections/azure/pull/1409)) + - Add missing Azure API Profiles ([#1395](https://github.com/ansible-collections/azure/pull/1395)) + - Fix MSI authorization credentials ([#1393](https://github.com/ansible-collections/azure/pull/1393)) + - Fix the `client_id` value ([#1421](https://github.com/ansible-collections/azure/pull/1421)) + - azure_rm_virtualmachine: + - Fix `os_profile` error [#1397](https://github.com/ansible-collections/azure/pull/1397)) + - Fixed disk mount error ([#1407](https://github.com/ansible-collections/azure/pull/1407)) + - Fixed properties mapping error ([#1410](https://github.com/ansible-collections/azure/pull/1410)) + - Detect the VM's `powerstate` value ([#1412](https://github.com/ansible-collections/azure/pull/1412)) + - Limit zones to at most one ([#1392](https://github.com/ansible-collections/azure/pull/1392)) + - azure_rm_*: Deprecate custom properties ([#1388](https://github.com/ansible-collections/azure/pull/1388)) + - azure_rm_networkinterface: Fixed `subscription_id` not used ([#1416](https://github.com/ansible-collections/azure/pull/1416)) + - azure_rm_adgroup: + - Update test cases to use `object_id` ([#1418](https://github.com/ansible-collections/azure/pull/1418)) + - Fix test case ([#1426](https://github.com/ansible-collections/azure/pull/1426)) + - azure_rm_adapplication: Fix test case ([#1425](https://github.com/ansible-collections/azure/pull/1425)) + + +## v2.1.1 (2023-12-19) + +### FEATURE ENHANCEMENT + - **/task/main.yml: Remove unneeded waits in test cases ([#1374](https://github.com/ansible-collections/azure/pull/1374)) + - azure_rm_securitygroup: Add upper letter protocol to security group ([#1381](https://github.com/ansible-collections/azure/pull/1381)) + - Update min Ansible core version to v2.14 - Ansible v2.13 EOF Nov.6 2023 ([#1382](https://github.com/ansible-collections/azure/pull/1382)) + +### BUG FIXING + - plugins/inventory/azure_rm.py: Restore the return of `public_ipv4_address` and fix the bug that the VM does not have a public IP address ([#1379](https://github.com/ansible-collections/azure/pull/1379)) + + +## v2.1.0 (2023-12-13) + +### NEW MODULES + - azure_rm_accesstoken_info ([#1318](https://github.com/ansible-collections/azure/pull/1318)) + - azure_rm_openshiftmanagedclusterkubeconfig_info ([#1238](https://github.com/ansible-collections/azure/pull/1238)) + - azure_rm_sshpublickey ([#1190](https://github.com/ansible-collections/azure/pull/1190)) + - azure_rm_sshpublickey_info ([#1190](https://github.com/ansible-collections/azure/pull/1190)) + +### FEATURE ENHANCEMENT + - azure_rm_storageaccount: Add support for `large_file_shares_state` ([#1210](https://github.com/ansible-collections/azure/pull/1210)) + - azure_rm_storageaccount_info: Add support for `large_file_shares_state`([#1210](https://github.com/ansible-collections/azure/pull/1210)) + - azure_rm(`inventory`): + - Add support for `include_host_filters` ([#1347](https://github.com/ansible-collections/azure/pull/1347)) + - Enhance inventory name checking ([#1348](https://github.com/ansible-collections/azure/pull/1348)) + - azure_rm_webapp : Add support for `http20_enabled` ([#1360](https://github.com/ansible-collections/azure/pull/1360)) + - azure_rm_webapp_info : Add support for `http20_enabled` ([#1360](https://github.com/ansible-collections/azure/pull/1360)) + - azure_rm_virtualmachine : Add retry logic for VM state synchronization ([#1354](https://github.com/ansible-collections/azure/pull/1354)) + - azure_rm_virtualmachinescaleset : Add retry logic for VM state synchronization ([#1354](https://github.com/ansible-collections/azure/pull/1354)) + - azure_keyvault_secret: Added support for `use_msi`(disable MSI autodiscover feature in `azure_keyvault_secret` lookup plugin) ([#1353](https://github.com/ansible-collections/azure/pull/1353)) + - sanity-requirements-azure.txt: Bump cryptography from `41.0.4` to `41.0.6` ([#1349](https://github.com/ansible-collections/azure/pull/1349)) + +### BUG FIXING + - AD resources : Fix get resource with CLI credentials ([#1364](https://github.com/ansible-collections/azure/pull/1364)) + - azure_rm_iotdevice: Fixed the issue of failed to obtain alias parameters ([#1278](https://github.com/ansible-collections/azure/pull/1278)) + - azure_rm_iotdevicemodule: Fixed the issue of failed to obtain alias parameters ([#1278](https://github.com/ansible-collections/azure/pull/1278)) + - azure_rm_virtualmachine: Support update `proximity_placement_group` ([#1329](https://github.com/ansible-collections/azure/pull/1329)) + - azure_rm_common: Fix the CLI authorization obtain token error ([#1340](https://github.com/ansible-collections/azure/pull/1340)) + - azure_rm_adapplication: Fix get application error ([#1345](https://github.com/ansible-collections/azure/pull/1345)) + - azure_rm_adapplication_info: Fix get application error ([#1345](https://github.com/ansible-collections/azure/pull/1345)) + - azure_rm_manageddisk: Support unmount disk from VMs in different resource group ([#1201](https://github.com/ansible-collections/azure/pull/1201)) + - azure_rm_resource: Fix failure on response for non-json body ([#1341](https://github.com/ansible-collections/azure/pull/1341)) + - azure_rm_deployment: Fix delete the whole resource group when state is `absent` ([#1231](https://github.com/ansible-collections/azure/pull/1231)) + - azure_rm_adgroup: Fix get group error ([#1355](https://github.com/ansible-collections/azure/pull/1355)) + - azure_rm_adgroup_info: Fix get group error ([#1355](https://github.com/ansible-collections/azure/pull/1355)) + - azure_rm_aduser_info: Fix get user error ([#1355](https://github.com/ansible-collections/azure/pull/1355)) + - azure_rm(`inventory`): Fix dynamic VM fetch failure when `batch_fetch=true` ([#1344](https://github.com/ansible-collections/azure/pull/1344)) + - azure_rm_adapplication: Fix parameter error ([#1369](https://github.com/ansible-collections/azure/pull/1369)) + +### BREAKING CHANGE + - azure_rm: Rename `public_ipv4_addresses` to `public_ip_address`and change type to list ([#1214](https://github.com/ansible-collections/azure/pull/1214)) + +## v2.0.0 (2023-11-17) + +### FEATURE ENHANCEMENT + - azure_rm_storageblob: Add support for `auth_mode` ([#1315](https://github.com/ansible-collections/azure/pull/1315)) + - azure_rm_galleryimageversion: Add support for `encryption` ([#1311](https://github.com/ansible-collections/azure/pull/1311)) + - azure_rm_galleryimage: Add support for `features` ([#1310](https://github.com/ansible-collections/azure/pull/1310)) + - azure_rm_apimanagement: Bump API version to `v2022-08-01` ([#1327](https://github.com/ansible-collections/azure/pull/1327)) + + - azure_rm_apimanagement_info: Bump API version to `v2022-08-01` ([#1327](https://github.com/ansible-collections/azure/pull/1327)) + - azure_rm_apimanagementservice: Bump API version to `v2022-08-01` ([#1327](https://github.com/ansible-collections/azure/pull/1327)) + - azure_rm_apimanagementservice_info: Bump API version to `v2022-08-01` ([#1327](https://github.com/ansible-collections/azure/pull/1327)) + - azure_rm_*: Add `hasattr` method to verify return value ([#1307](https://github.com/ansible-collections/azure/pull/1307)) + - azure_rm_virtualmachine_info: Add `vm_agent_version` to output ([#1289](https://github.com/ansible-collections/azure/pull/1289)) + - azure_rm_virtualmachine: + - Add support for `os_disk_encryption_set` ([#1306](https://github.com/ansible-collections/azure/pull/1306)) + - Add `disk_encryption_set` for data disks ([#1309](https://github.com/ansible-collections/azure/pull/1309)) + - azure_service_principal_attribute: Move `azure_service_principal_attribute.py` to azure-collecitons lookup file ([#1326](https://github.com/ansible-collections/azure/pull/1326) + - azure_rm_account_info: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adapplication: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adapplication_info: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adgroup: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adgroup_info: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adpassword: + - Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - Add support for `display_name` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adpassword_info: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adserviceprincipal: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adserviceprincipal_info: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_aduser: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_aduser_info: Migrate from ADGraph to MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - pr-pipelines.yml: + - Add ansible-core v2.16 ([#1305](https://github.com/ansible-collections/azure/pull/1305)) + - Update PR validation pipeline timeout to 180 minutes ([#1334](https://github.com/ansible-collections/azure/pull/1334)) + +### BUG FIXING + - main.yml: Ansible `is match` does not need a `^` ([#1321](https://github.com/ansible-collections/azure/pull/1321)) + - azure_rm_virtualmachine: Fix caching choices ([#1324](https://github.com/ansible-collections/azure/pull/1324)) + +### BREAKING CHANGE + - azure_rm_virtualmachinescaleset: `orchestration_mode` defaults to `Flexible` ([#1331](https://github.com/ansible-collections/azure/pull/1331)) + - azure_rm_adapplication: + - Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - Deprecate `allow_guests_sign_in` as not supported in MSGraph ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adapplication_info: - Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adgroup: Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adgroup_info: Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adpassword: + - Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - Deprecate `value` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adpassword_info: Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adserviceprincipal: Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_adserviceprincipal_info: Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_aduser: Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + - azure_rm_aduser_info: Deprecate `tenant` ([#1325](https://github.com/ansible-collections/azure/pull/1325)) + ## v1.19.0 (2023-11-6) ### FEATURE ENHANCEMENT diff --git a/ansible_collections/azure/azcollection/FILES.json b/ansible_collections/azure/azcollection/FILES.json index 3ef548ee8..57fe6593a 100644 --- a/ansible_collections/azure/azcollection/FILES.json +++ b/ansible_collections/azure/azcollection/FILES.json @@ -8,2845 +8,2845 @@ "format": 1 }, { - "name": "README.md", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "5c2cfcffcf93c51cab4c38238a262431adacb67bd106fd484e730cc8cd17679c", + "name": "meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "shippable.yml", + "name": "meta/execution-environment.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "515333579eea59619360d72e38cc2c5c9a8b43ff59cd3ddcc12c5b0172553b4a", + "chksum_sha256": "4ed6d806d5b0456d5d6ab6e46d68bdbe7b46b10b4352a80ae8b8487220337742", "format": 1 }, { - "name": "requirements-azure.txt", + "name": "meta/runtime.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "575dc8b28a49511996ebd91849dc2d61bc5789bf68d2e1c28c9309a7d2ddc887", + "chksum_sha256": "d034d1f9a361fef10f399b0a9e563b6b08df2a190432b69aced0323849298fcf", "format": 1 }, { - "name": "meta", + "name": "tests", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "meta/runtime.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f348a65f8d5a078d41b7f9608bef523b5a63d577cea802bb31755bd21c62fd01", - "format": 1 - }, - { - "name": "meta/execution-environment.yml", + "name": "tests/config.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4ed6d806d5b0456d5d6ab6e46d68bdbe7b46b10b4352a80ae8b8487220337742", + "chksum_sha256": "410698cc625c851ec21f2ef8ea020cf7a353590d10a995a3c57eb52d4d8065fb", "format": 1 }, { - "name": "pr-pipelines.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b58b22a0b119202301503af60a15be12426baa3a8c9c82928bea87c9706b2979", + "name": "tests/lint", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "CredScanSuppressions.json", + "name": "tests/lint/ignore-lint.txt", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "98c0ee6a0b7a115787cf109a8c0e2ea4a61df6751ecda37915b22ffb44a1128d", + "chksum_sha256": "bea1480e79bf52af44c7d7b2b112aead789a54696c6ef6469f2dcd710ad2a47f", "format": 1 }, { - "name": "plugins", + "name": "tests/utils", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "plugins/lookup", + "name": "tests/utils/ado", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "plugins/lookup/azure_keyvault_secret.py", + "name": "tests/utils/ado/ado.sh", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6f20418149499651d651da69502e509ad913074c5da1d4005a37b86b96eda0ce", + "chksum_sha256": "6e74c310ccc00f71866dc1cd4bc73a66de6a38b2d8dceb2aef6d8bf2a20908f9", "format": 1 }, { - "name": "plugins/doc_fragments", + "name": "tests/utils/shippable", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "plugins/doc_fragments/azure_rm.py", + "name": "tests/utils/shippable/sanity.sh", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e19514cc0040e3b896fe05729dc6d5c5bc22698aff5bfa12d85e5195fb019634", + "chksum_sha256": "1cd365c5bad1facb7e98cad97a20e34231f49fca169653ccd7d34bd955bd88f6", "format": 1 }, { - "name": "plugins/doc_fragments/azure_tags.py", + "name": "tests/utils/shippable/timing.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e8c9d720dbc7605d3ee66799e8e81d0886e404c9a07b6b9b8edc844e0646de64", + "chksum_sha256": "8236af7a7c739bbc2309ae15e1b59b46274fae86e6d925271562b4dc445833af", "format": 1 }, { - "name": "plugins/doc_fragments/azure.py", + "name": "tests/utils/shippable/azure.sh", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "57355ef9f93df996e93a187c7625073757b8a33df701383f756b3829457adae9", + "chksum_sha256": "99db6946e47cf9e49ab2fccbe0aca8ffc9aaa0918fdc9e3ef543601c55a98713", "format": 1 }, { - "name": "plugins/module_utils", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/utils/shippable/timing.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f3f3cc03a997cdba719b0542fe668fc612451841cbe840ab36865f30aa54a1bd", "format": 1 }, { - "name": "plugins/module_utils/azure_rm_common_ext.py", + "name": "tests/utils/shippable/shippable.sh", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ebf7c0c6f4ad7a05a04d740ca989a05cc4b22728acbd6390d9aa90931eca1647", + "chksum_sha256": "829380ef8b40f42a82696ada1168318856596f4e943bbb9a4f5cd6130bbce2af", "format": 1 }, { - "name": "plugins/module_utils/azure_rm_common_rest.py", + "name": "tests/utils/shippable/cloud.sh", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "81845c1924ae3be8f567d3d1eac2c01ddb1ae2a6bf72d41197423b4f37e59253", + "chksum_sha256": "99db6946e47cf9e49ab2fccbe0aca8ffc9aaa0918fdc9e3ef543601c55a98713", "format": 1 }, { - "name": "plugins/module_utils/azure_rm_common.py", + "name": "tests/utils/shippable/check_matrix.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "54a254f8975e14c17a5e60c7727ff1eb540e3027b1622066197184d5cb449267", + "chksum_sha256": "49ae66e3ec8931f5f534a038ede5b3c5c95d57eb2e96945458fcb718f6e5b2d5", "format": 1 }, { - "name": "plugins/inventory", + "name": "tests/integration", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "plugins/inventory/azure_rm.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "bed3077d86f3b8db29b588d99a2f8899e8b1c1a745727d85719ad9a1d264b71a", - "format": 1 - }, - { - "name": "plugins/modules", + "name": "tests/integration/targets", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabartifactsource_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "53f584ee94c091e0879eb336194eaef6b94504dfe999f493bd1d029e30d03127", + "name": "tests/integration/targets/azure_rm_notificationhub", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_gallery_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "e1b22cd1253e69c51442a1e402ef64fbdccaa8ce61b05839041fd7c35a5a44ab", + "name": "tests/integration/targets/azure_rm_notificationhub/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_automationaccount_info.py", + "name": "tests/integration/targets/azure_rm_notificationhub/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "048a0c9b532196427437575202beaf31f8314efb70c67aa86733e6cccc14a98c", + "chksum_sha256": "a66dc9e034ad04e167bd52df4f75f2bea4499b25349fc42b3c8de9e2fe806996", "format": 1 }, { - "name": "plugins/modules/azure_rm_privateendpointdnszonegroup_info.py", + "name": "tests/integration/targets/azure_rm_notificationhub/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "70582f1fa2c40f77e166f00242bd6bff2e7c018368beaa2ac960328c341faa77", + "chksum_sha256": "1be076424fbf717d678e202250426e9b368688f8d3029f0c5dc262b97df819af", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualnetwork_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "39cbe4ccb66acb4dd36b893c9cb000846535c0726b8960e541a47f576fa2ed6f", + "name": "tests/integration/targets/azure_rm_notificationhub/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_rediscache.py", + "name": "tests/integration/targets/azure_rm_notificationhub/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2323900cb0386fdd65ca6edada0a669ae12d6d87a9c08afb9bc92e150612a36d", + "chksum_sha256": "7f519a0026da2e72a6633b7e82a4c2ae581c50b918a5291b3b4737360211276b", "format": 1 }, { - "name": "plugins/modules/azure_rm_privatednszone_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "d1ed854fff931a8a0295b9a4f82235bb9ed8cf5bb947377c51931bcf94dc4c9f", + "name": "tests/integration/targets/azure_rm_acs", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_mysqlconfiguration.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "fff34c89e959affced009f321ef5cd6b6ad9955e711d69306f339ca4c15392e0", + "name": "tests/integration/targets/azure_rm_acs/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_loadbalancer_info.py", + "name": "tests/integration/targets/azure_rm_acs/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b6b508842cc40fd4310a90e2bbad7733a50b7c43e29dc73dbccb304940b0f53c", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_ddosprotectionplan_info.py", + "name": "tests/integration/targets/azure_rm_acs/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9ea0ae1f2bcab647085f83b8223d763abf123afe3996d0aeb0f304fc8d4fc7d3", + "chksum_sha256": "2f7e954a810d0341b1aed1d34e5684bc502980bb6ebbe6a46fb03163ed0e11db", "format": 1 }, { - "name": "plugins/modules/azure_rm_hostgroup.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "7f3b26f577bb53702d0ed884da4c0c587dc6a186b7bdf9b87d3765c7dadcd89f", + "name": "tests/integration/targets/azure_rm_acs/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_datafactory.py", + "name": "tests/integration/targets/azure_rm_acs/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5e54eadbb395d175730960b6e089b78c76cefeebe08dca0ab1ae80e4d34e78fb", + "chksum_sha256": "ecad2cdce0986a34a8f64d2bcbcbd742d99a0083d4e2773cc6a5482a5d529b9c", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachineextension_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f845763404b68b32efe0187e0224cf30b7c71366531b4de508089df01f4849a3", + "name": "tests/integration/targets/azure_rm_webapp", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_dnszone_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "15da62156897e9dc73a74650198e57b4d6dce5bb761b1e0b0c86d19be31f1cce", + "name": "tests/integration/targets/azure_rm_webapp/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_rediscache_info.py", + "name": "tests/integration/targets/azure_rm_webapp/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "af3900d503ca2de80407fa58b2a09e2835a2087315d12a6ae70145f738a71120", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_iothub.py", + "name": "tests/integration/targets/azure_rm_webapp/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aee9f30afbc1989ff7cfe64101c59d842dc635e59b34411d4045c428f1109b1d", + "chksum_sha256": "75b6fa7694979e088e4b068016381f37a603045a395e3b8c660032f4008257d5", "format": 1 }, { - "name": "plugins/modules/azure_rm_mysqlconfiguration_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "d9e284a3a0c4c2ec47a44ac4a7419358ab7d897488fa29de3ae616cfed56ec4d", + "name": "tests/integration/targets/azure_rm_webapp/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabvirtualmachine.py", + "name": "tests/integration/targets/azure_rm_webapp/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b851e89e72b71469d5eeefb555948de70ae6372728745fa25761ab952164ae08", + "chksum_sha256": "9774c1a314a6b5fef489d9405550a1395b9468bbea779af6ca95ae47af6386a9", "format": 1 }, { - "name": "plugins/modules/azure_rm_backuppolicy_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f16cb70c198028b5273e9d89ad554ed6a8e40217284a1fafb9658121c415b4b0", + "name": "tests/integration/targets/azure_rm_postgresqlserver", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_batchaccount.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1010400ee7ceae601c41e97f30336b2732cdab7edf899ab95edf706f1470f0da", + "name": "tests/integration/targets/azure_rm_postgresqlserver/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_cognitivesearch_info.py", + "name": "tests/integration/targets/azure_rm_postgresqlserver/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8e5e926aea80ecc40b2a0c06745ed85287f4f6f83692af2ad78e7ea641c8d463", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_managementgroup_info.py", + "name": "tests/integration/targets/azure_rm_postgresqlserver/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "728bb535e8dbf3211e4a79123dfa981434dc51423efb046e2bfa6cb35c5949f6", + "chksum_sha256": "212c2162821130244834f49afd3460bb037d426eac902fc88de51afbe6bab522", "format": 1 }, { - "name": "plugins/modules/azure_rm_lock_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a176ee61fc34ddb3afb0a07d267ce819f0b85f1e271ae4f52f51004869014d21", + "name": "tests/integration/targets/azure_rm_postgresqlserver/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_containerregistrytag.py", + "name": "tests/integration/targets/azure_rm_postgresqlserver/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9b6a6b029d0bff63cc6fd9cbbbc92f44337fd23d460747b942a4caf32731ad05", + "chksum_sha256": "957431198f2f2412d381532922a380b37d3a2941dce8f6fbcda89284fa7d3ca5", "format": 1 }, { - "name": "plugins/modules/azure_rm_proximityplacementgroup_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3e049bd091a4b88b2d68b6462d3cc15d740fcc65f5d3e310496513be40a83661", + "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachinesize_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "24e4730a6256f17cd27877328ed90580bcd2ac93c1b3718b70e18d8c574769a5", + "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_vpnsite_info.py", + "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "63c87ba7508bb5c7e2f4968c4975b8e85e27260474dcb6f7d558295f9c56a946", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_keyvault_info.py", + "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "42dc1992f6870d92fb0c00e196491d148037561a16f1a3980da71a450d8d1150", + "chksum_sha256": "cc618d5714ddaae8f1482cf89dcf3327cf82fa378c16f6b5cf092339927261c3", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualwan_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3e7d2fdf7181de1499b68196f176080a9563767764ee9bb27bf3e3411cb87a75", + "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_registrationassignment_info.py", + "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ebee000acc1f85898adb717c015209d78a231d7a4130d20293c103c1e01dc57f", + "chksum_sha256": "4c185b22edc1017409894f57875fe5db2c986c6d741cbd86dc78aa01b36a9fc9", "format": 1 }, { - "name": "plugins/modules/azure_rm_sqlelasticpool.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a127cd3108b9eff43c793296f6239ee10df0810222dae4c44b380e45c01e36eb", + "name": "tests/integration/targets/azure_rm_subnet", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_routetable_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1e849400c3b71a0bb6652ab1d40e919288b3dccb94314230273850f31259de8b", + "name": "tests/integration/targets/azure_rm_subnet/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_diskencryptionset.py", + "name": "tests/integration/targets/azure_rm_subnet/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d4f85b7a7c7da95b7fbd3a084a15af87fd037134c527056a14f48ae1e58b9a9f", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_storageshare.py", + "name": "tests/integration/targets/azure_rm_subnet/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d70dd044b1bf421773c6438c7c9020906810f7e1e74523e8855133a8fae9360d", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "plugins/modules/azure_rm_mariadbconfiguration.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f54c337f3d115d08dcac88d6e4fe16ef1db3d9dec1833b033928f227d89ea11b", + "name": "tests/integration/targets/azure_rm_subnet/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_eventhub.py", + "name": "tests/integration/targets/azure_rm_subnet/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "aeadcc0ec44f966ae318556be223ecbbe4198c412c9d34d1360d724aa919ce0e", + "chksum_sha256": "6da3c97478624fb4d675d4787caedba75a8b159228bc39d6fccdd3db6a333c78", "format": 1 }, { - "name": "plugins/modules/azure_rm_mariadbconfiguration_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "783f344263d15fef8444cab2f98286515b584c64945f759d1c45ab3363ae1304", + "name": "tests/integration/targets/azure_rm_subscription", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_subnet_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "781c564f40087d071942dab53c627fed093764c5a244744874e2226ec174bee8", + "name": "tests/integration/targets/azure_rm_subscription/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_functionapp_info.py", + "name": "tests/integration/targets/azure_rm_subscription/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1e0f3de0ed340f2e1a5cb2b5b4cb8b7cc9c6c8eafe4483cdb38b58878482b589", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_iothub_info.py", + "name": "tests/integration/targets/azure_rm_subscription/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ceef9d30aeb4826188b1c96a6d955955e99ae90a1e8b9ff437859f82a3cdd5a", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "plugins/modules/azure_rm_batchaccount_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b823cdf2a1c2c41c40d0db12e5bd637598f388db9beb0eb2e79e1c940aed39d6", + "name": "tests/integration/targets/azure_rm_subscription/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_aks.py", + "name": "tests/integration/targets/azure_rm_subscription/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3da4a613aad9785a4d3b764ef386699d796167b12c9291019fb17a204fbd9db5", + "chksum_sha256": "cb18a11b4b6b14912f9fcc0131c232c9d3525d14a8d43ee4b2606cc2d3f7249c", "format": 1 }, { - "name": "plugins/modules/azure_rm_networkinterface.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "7216e23eac5fe34435ac3f8cb111b6c68cab283ec4dba61a4c9efc805221e8df", + "name": "tests/integration/targets/azure_rm_appgateway", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_subnet.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "0b0cf9127582749f7d680b30cf94545c7ccf6b2a1d28903387ea3bae45e14ef7", + "name": "tests/integration/targets/azure_rm_appgateway/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_cdnprofile.py", + "name": "tests/integration/targets/azure_rm_appgateway/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8051fcf46e6ef1061831461ded14aa4fad1a59c7a5dfdfd3d90d6816db8df475", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_azurefirewall_info.py", + "name": "tests/integration/targets/azure_rm_appgateway/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6d62301f903c8d8e1075bb7d29412f91b65136344d0fb915eb5017f8936142d9", + "chksum_sha256": "21442459796e3c03ab3c6461c8251810f5545ff2320c4c814cce8b8c520e615c", "format": 1 }, { - "name": "plugins/modules/azure_rm_roleassignment_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3287b7ad7063115ef66dc443b05f4ceb6bd22d46cd8fcec1350c6e9e64289b3f", + "name": "tests/integration/targets/azure_rm_appgateway/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_adserviceprincipal_info.py", + "name": "tests/integration/targets/azure_rm_appgateway/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6ec6a6ab5cd644af2cc67b32e41258e058a5e7cad8b9d45a25eb7865edceda0e", + "chksum_sha256": "7d8ffa4ec62e8b5bcf85c4c36004a71daf4b8bf455238a1b6a8a1749fd64bd4d", "format": 1 }, { - "name": "plugins/modules/azure_rm_webappvnetconnection.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "5f823a8fd9802af336c53b103f05d687a20989e92334d7bc122f7ccb62a6a410", + "name": "tests/integration/targets/azure_rm_appgateway/files", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_hdinsightcluster_info.py", + "name": "tests/integration/targets/azure_rm_appgateway/files/cert3b64.txt", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9531f6f0a60132fb1ab9b2e49ab271ba1a630f75682b44197f61632daacb1a0b", + "chksum_sha256": "1375dc6f493fb760c6087c4cdd62c4ea898887070ad17dc84196b3d6ed0545ec", "format": 1 }, { - "name": "plugins/modules/azure_rm_securitygroup_info.py", + "name": "tests/integration/targets/azure_rm_appgateway/files/cert2.txt", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "961d9d5ad4d46ff1acf101c19ebd88813d5251f89ec7e1f4ea809827cc3b5392", + "chksum_sha256": "e4dc34faa2e8e94cd385be73c33a849f452dd57d061a8aec118e6d391e46bbc0", "format": 1 }, { - "name": "plugins/modules/azure_rm_servicebus_info.py", + "name": "tests/integration/targets/azure_rm_appgateway/files/cert1.txt", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "56677b7274f63fe629975901c0c3f2239a58b3b44d6f42d5e8327e283c49cf22", + "chksum_sha256": "7637ce7f36cca366294688f612f6456714088cca19583ae7e9475e572d85f4f5", "format": 1 }, { - "name": "plugins/modules/azure_rm_natgateway_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "05d862d157fc493cab345fea70f17c3913624364407562a9a2d884377f69f586", + "name": "tests/integration/targets/azure_rm_privatednszone", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_deployment.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a51562a752c8d9f77ea8afa4ab966ece92c6d868f7eb939a9adcc28c800fbc2f", + "name": "tests/integration/targets/azure_rm_privatednszone/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_adgroup_info.py", + "name": "tests/integration/targets/azure_rm_privatednszone/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8e06b65183c867879b4f34b3b65c24e1d77d6fa1007b90c7f433e658b418d9cf", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachine_info.py", + "name": "tests/integration/targets/azure_rm_privatednszone/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "371f0c2e8c15271dcede607bb8cfc52469b506a12b2e3f74adcb7d8beabff4b9", + "chksum_sha256": "e131092efb0e9d778baeb38471a15da9b4f8ab9e3425ec4f37aaece309220d47", "format": 1 }, { - "name": "plugins/modules/azure_rm_privateendpointdnszonegroup.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "d516440379341b68c65581c8d9da78f6a204845502e408c48875851c58229241", + "name": "tests/integration/targets/azure_rm_privatednszone/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachineextension.py", + "name": "tests/integration/targets/azure_rm_privatednszone/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "09bd02e50c12aa9e602e8ac7b4312b2619be27b656114309625c9aa39fbcb97a", + "chksum_sha256": "b2de5836a16a64f95f0494dd53d54cd82716c1133e7707c0c2680d9502dfef5c", "format": 1 }, { - "name": "plugins/modules/azure_rm_roledefinition_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "20f17bd7a42d8ebe0d377d9c81754be478f94591e038c65850658c3be6b88422", + "name": "tests/integration/targets/azure_rm_accesstoken_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_privatednsrecordset_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "ca64fe771c93ee29952634b1acd63d8ae35c0f36b4ef3a33f6ac1ef0994e2e42", + "name": "tests/integration/targets/azure_rm_accesstoken_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_roledefinition.py", + "name": "tests/integration/targets/azure_rm_accesstoken_info/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2916e92b6ed98170b35ff1c4bbd3a970ffa11323b2bbb01e37271110072ed33d", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_proximityplacementgroup.py", + "name": "tests/integration/targets/azure_rm_accesstoken_info/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c39137e4926c1749a04adc516a027a08e7cf2ebe2b21e7a95675fd0a546777b9", + "chksum_sha256": "d57abe6f8fb0cbfb8ac22431c09126cd48bb4d2836a6d151faf92fb6fbecc6aa", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualhubconnection.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "2b3ba5bbf31b9e64c4e0978fa92768ce9115fe39450f5dd8085c775fe4ed2716", + "name": "tests/integration/targets/azure_rm_accesstoken_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_eventhub_info.py", + "name": "tests/integration/targets/azure_rm_accesstoken_info/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "840c5f5441849b9ae7c489f04bb2fd065cc4192ca4a8143c1fc052c2845e002f", + "chksum_sha256": "89df9eb85892a54536cf07ef674d75b60c910eee66147eefb074aef8c23108d4", "format": 1 }, { - "name": "plugins/modules/azure_rm_sqldatabase.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "4ad23bc0505f7a62a03434a0c94c2eaf90ed06c4d5e4ccbf05f169de465fd693", + "name": "tests/integration/targets/azure_rm_recoveryservicesvault", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_webappvnetconnection_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "cbb81f50bdad8e9d738f6a8ff9566898df41fec03e92e3b03383228de5607fff", + "name": "tests/integration/targets/azure_rm_recoveryservicesvault/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_servicebustopic.py", + "name": "tests/integration/targets/azure_rm_recoveryservicesvault/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3061e6f04b67b71c3c7d09566a35916f130745ffc7dd1b472385d78587140da3", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_resource.py", + "name": "tests/integration/targets/azure_rm_recoveryservicesvault/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "546c902f77832ea142cffe5b07b7babab61081094e713733857f4efaaf71aa63", + "chksum_sha256": "923b442d786cff06e0b7a3ea4232f7bfe10835e93fb73b8df6ee997380099420", "format": 1 }, { - "name": "plugins/modules/azure_rm_firewallpolicy_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1e1cebf4f29a286751549a9a5ccf06451bfb9648151d54ca813646f1289dc8b9", + "name": "tests/integration/targets/azure_rm_recoveryservicesvault/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_containerinstance.py", + "name": "tests/integration/targets/azure_rm_recoveryservicesvault/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b3c13189f840de2aa3047eeb145d3f1680c40a999a45b92325f70a92ff950296", + "chksum_sha256": "6e841ad32da809ed4a9782a8ce178f2c8399d98a56be2406142e898afffb65c0", "format": 1 }, { - "name": "plugins/modules/azure_rm_adpassword_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "6cc6cf20421203712d3890dbe04dcf4c96d7ba99f3eff6d700d03addabeb93fa", + "name": "tests/integration/targets/azure_rm_iothub", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_postgresqlconfiguration.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c5a5c9f631bc9ef1eb1d64acd039457dc38a52c84e5246589b9f42df904aa37a", + "name": "tests/integration/targets/azure_rm_iothub/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_mariadbdatabase_info.py", + "name": "tests/integration/targets/azure_rm_iothub/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "abe1fd7778f01c877a7c8d74170c74a26e39de0d5295b3e856adcc39fc7367e8", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_backupazurevm_info.py", + "name": "tests/integration/targets/azure_rm_iothub/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4e25e335897973b2afb89187cbd96429e89fe688347be78a73dc4049c3dc3986", + "chksum_sha256": "8d4097a5a2543084f3eea11259e299ba87ade8dc8995e5745358931356bee79f", "format": 1 }, { - "name": "plugins/modules/azure_rm_cdnprofile_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "11acb43afaee020e3b3c252d5c1d3e9669ddcef8f3941635b1bce4d411b9c12e", + "name": "tests/integration/targets/azure_rm_iothub/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_backupazurevm.py", + "name": "tests/integration/targets/azure_rm_iothub/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b1d8a252ccfac8973cf591771b6d7149c2bbf4f788366e1dc2b16fef8d52cc61", + "chksum_sha256": "1e5e67ce46e6ae0d5e38dbc0526e3140c3f1f3d978883736c4c84e0732042dbf", "format": 1 }, { - "name": "plugins/modules/azure_rm_resourcegroup.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "20900d4b10ee5f7032fc409be2eaafc00521f8799c56559d8ac88fce00e4b2eb", + "name": "tests/integration/targets/azure_rm_aksagentpool", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_datafactory_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "97332f814785d6c0aad03a37f0126454115c0f219379529fefa421bf9ea20b53", + "name": "tests/integration/targets/azure_rm_aksagentpool/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachine.py", + "name": "tests/integration/targets/azure_rm_aksagentpool/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a71e48a19a1f43d47a46951e936b6cf187ea87170d247326449f9a6fbdd1bc79", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_gallery.py", + "name": "tests/integration/targets/azure_rm_aksagentpool/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d75d837aeb5b9292babe25fd49f7b24e516c4ae3ac3707afeab09bf801cdc711", + "chksum_sha256": "783d6dbd1b9cc4b0543d6e96d15206283018e0c291764a2a4106e860d41cb210", "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabenvironment_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a33bd3a6e60f1153b611e1f45fc4c99b01b9ff2342e92171e823bd8016b2be0c", + "name": "tests/integration/targets/azure_rm_aksagentpool/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabvirtualnetwork.py", + "name": "tests/integration/targets/azure_rm_aksagentpool/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4c52da65b8749ffc924d5206dc8a4f29406dd208cefd20ca78cd5f30c9184e77", + "chksum_sha256": "88959c5262b2f543793b47314b9bce24d267e32f9c3f419f71a242dbbccadf12", "format": 1 }, { - "name": "plugins/modules/azure_rm_containerinstance_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "ab1aa37508addc2bf616e2c13664f2a1e5e0235af91db2bb84542449d01fc67b", + "name": "tests/integration/targets/azure_rm_virtualmachine", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_cosmosdbaccount.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/runme.sh", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d6c644934b50c99c8839405f78cae5aea90c0f6b2a9ae4f74a9f761467ea7cd1", + "chksum_sha256": "8d9a70f8c75d9a856cd529ae8ccb6e589c0db9494da4bb08cead6963e98d9dd5", "format": 1 }, { - "name": "plugins/modules/azure_rm_mariadbfirewallrule_info.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7a2b125c6e0ed19d1fe70703e24ed9e4257713c492e927785fe35cdf789afcc2", + "chksum_sha256": "deefc8fe8e3699aa1e8852f316f52c0037219050b5b5d07919fa24d06ac14ed5", "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabartifactsource.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1b3f24465ae9f40d6adc4e61d6e1f34d78345b5ee88c5c5958ed401b3146b79d", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_keyvaultkey_info.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_no_public_ip.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "23eaf4510c03b121fc24ba8a116b26e35563af5ee9875d7210557caf2e6ce9b2", + "chksum_sha256": "a7f201260799a21031f75d3ecbd6cc372007c3a2c5ef7a6c9d35053129b868cd", "format": 1 }, { - "name": "plugins/modules/azure_rm_trafficmanagerendpoint.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_minimal_manageddisk.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "48772694d9d17d8d0f6b0e6d44c4359dbb35861116c38fa933b0db93981f7a76", + "chksum_sha256": "e10179f3c286b53a8347a1cd7d3672cc80e9184589dc7ea292489279fcc67ede", "format": 1 }, { - "name": "plugins/modules/azure_rm_mysqlserver.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_dual_nic.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7f7cb3ce5875e72550cd314cc3df490cbbce0292265c927038897d026b573514", + "chksum_sha256": "270c196e70cd74c25954f6e5e2acd136aef9e3892f36051663ff6a96d5f984c8", "format": 1 }, { - "name": "plugins/modules/azure_rm_mysqlserver_info.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/setup.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "595b1221845b1ff1d61c133eabb34930f9e9d0b59cd2ee853cddc487b182c57b", + "chksum_sha256": "1af862edc4a550cf631bcaa7a082d23451a3e7eacd0a248e4688bcc8dc6ef604", "format": 1 }, { - "name": "plugins/modules/azure_rm_cdnendpoint.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_public_ip.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7e105391561b1552efc4ea6e587d5a9dc60c61c6e7847ea036481b5923a10f26", + "chksum_sha256": "fc7a86147194125bacfe94a37a05af001ff6d68b6ee5b759d6561ceea51b6b33", "format": 1 }, { - "name": "plugins/modules/azure_rm_vpnsitelink_info.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_spot.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c12058e056680201ef2358025ed148b9338a50eebace5b8784cc9acdc525093f", + "chksum_sha256": "40cfa7a636a0741e3f17deb1c7b965fbc42074f3fb7a50503dc93b9c2515a2e4", "format": 1 }, { - "name": "plugins/modules/azure_rm_multiplemanageddisks.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_minimal.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "95a1386da7e22dc74338466668e3542f37584f4272481fc56b298ee95053d23e", + "chksum_sha256": "6ec63fe982d7ce8d65dadd74eb7e5c3678fa88e008ddfeaa43b1d3b77e094583", "format": 1 }, { - "name": "plugins/modules/azure_rm_iotdevicemodule.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/setup_des.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b8bc59ae66ec54ff0773dfe858b91a946df973f93e06c12b571b20d16a2142e6", + "chksum_sha256": "78451a10252f870ed0dffd1c7ef008265abf0573b7748d6518ced071c6a15df7", "format": 1 }, { - "name": "plugins/modules/azure_rm_azurefirewall.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_image_latest.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "da90ad6d785772e86a709e378eca2143faf638bfe60f3d362d578ec54302a0ac", + "chksum_sha256": "1d3000da1ae66217ff40113749e77538bee7ebf49e1808ad36488ca33d89761f", "format": 1 }, { - "name": "plugins/modules/azure_rm_loadbalancer.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_image_specific.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "40bcb2a088750276d350e5170a7993a5e92117948835d6bd30dcf5989db2cf11", + "chksum_sha256": "41a71c6515836e0c1c764ae83a0c999403e1fb774a55c5ab7912bdf7f1e2fc89", "format": 1 }, { - "name": "plugins/modules/azure_rm_trafficmanager.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_vm_identity.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9aba8d8ba13076c53f797b5c999af3dbc951849450ca138ce6572804eed67a22", + "chksum_sha256": "a7b73bb1af0583758961a25336d5faa2eb76fe6e84b3b9698b1bc5e53fbe4f9c", "format": 1 }, { - "name": "plugins/modules/azure_rm_registrationassignment.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_encrypted.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "075669114ff7606dbf4aa144d0e7fc51441b7ec8230c36f2951884d40ea502b7", + "chksum_sha256": "75d1bcac216eed0c0d847c74ad9f5b79b0f7bfbe7a34f08c3918a9baeaeac106", "format": 1 }, { - "name": "plugins/modules/azure_rm_galleryimageversion.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_no_nsg.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dfdc102dca75eaba97460f3f9a47a0ae0eb375714b030959a3781c9e12d675e2", + "chksum_sha256": "97017436c84bdbc87de46cee90cfab5edd108685b439253083f141cd5fd52a78", "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlab.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_invalid.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e45418f49d7b45ab7a6c29f17bc6f12cc0607a21179fce4a4f428d1419b1abc1", + "chksum_sha256": "055893c82ae8b817fbcd3287b7435ae35ba8d6825ad3cb9545048ac599f9dd56", "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabcustomimage.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_ephemeral_os.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4398962a6b78efc7b3faabd07af0cf4c31eafe25ec2fc23430a7385fd3c2050a", + "chksum_sha256": "a7ecfe0131bd01e748de4f813746530f25a2bcd906e582767d0417827d784937", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualnetworkpeering_info.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_deallocate.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "70b548cc3d9362d2c6a3c0ddedbded5ec61be98334bb43d0c59cad8a95065898", + "chksum_sha256": "6eb8b380f4e4e8f2dde24fe08098219bd067bf4b362e647df83b91d3e9133666", "format": 1 }, { - "name": "plugins/modules/azure_rm_hostgroup_info.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/inventory.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "05d3069e290c810fe454923e22f4aae4932aa8924b12d872039904d87b779a07", + "chksum_sha256": "dbfa6b4c9d720fa3c687dfb4c1101701708593184aaf0950ea66cca1f7bf63eb", "format": 1 }, { - "name": "plugins/modules/azure_rm_openshiftmanagedcluster_info.py", + "name": "tests/integration/targets/azure_rm_virtualmachine/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "061e20df32528b861d5ccdabd7b7e8bd5abdcf0ea2c3c973f561e656223ce0b4", + "chksum_sha256": "49c03342521da6b25da0d4df975ee81e10e8b1e7ebd1bdabeba797463bceddbe", "format": 1 }, { - "name": "plugins/modules/azure_rm_appgateway.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "04b1dd5413cdc81f642e470db6cdd1ae1ffa77d2b9b42e845b4bbf111235b650", + "name": "tests/integration/targets/azure_rm_functionapp", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachinescaleset_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "5925fb4d64f27c1460dc96e40aaa1eabda5612174aa598a717856b2861540662", + "name": "tests/integration/targets/azure_rm_functionapp/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_galleryimage_info.py", + "name": "tests/integration/targets/azure_rm_functionapp/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "89a14ee3f36038d0da78d7f7b586361e5acab82f1cd66c1c8278d840e12e2023", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_cdnendpoint_info.py", + "name": "tests/integration/targets/azure_rm_functionapp/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6d355f726042e8bb6f9729fbfe486980b2a88813cff5a9f92017a0df75ab2f48", + "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", "format": 1 }, { - "name": "plugins/modules/azure_rm_route_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "ec951f25bdc8b4944f43e054e44fc1887fbdb8cfaf892f5ce57174cf251b442e", + "name": "tests/integration/targets/azure_rm_functionapp/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_automationaccount.py", + "name": "tests/integration/targets/azure_rm_functionapp/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5dd5fd70d816d33733de4bd4eb9f7569038760a5d13f9f932d7cc94b8077bbf4", + "chksum_sha256": "a5d18ded0b871348c349b69152916bc7b243670fdc7ec9a2f8ab479ce589e390", "format": 1 }, { - "name": "plugins/modules/azure_rm_keyvaultkey.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "d9e0b37c1eb77dc2d8efe7a97a0715f2d381a59937cc6ff5ed8a7ce769ab558b", + "name": "tests/integration/targets/azure_rm_account_info", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachinescalesetextension.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a8ef46432cfcc51726f0e9d1ce8003a5e9820432a253d897b420c8423c178f74", + "name": "tests/integration/targets/azure_rm_account_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_mariadbserver.py", + "name": "tests/integration/targets/azure_rm_account_info/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6c671f81b7aff21b252b4844b16135a8fef889b340f66337e394d87e249e4a28", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_firewallpolicy.py", + "name": "tests/integration/targets/azure_rm_account_info/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "58980ae98ef0f3eb07237bd685eaf312369a68a484aaebef40037697d83cdec1", + "chksum_sha256": "a58bdac3b7068e244f2cf71f0a1a0bf136bc8785d2a8947fecbafdd97313adb7", "format": 1 }, { - "name": "plugins/modules/azure_rm_deployment_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "2b2f239c18ae7533a69c8a3e380840171bedc20dc4330ffb0b0f14c9cc5bda25", + "name": "tests/integration/targets/azure_rm_account_info/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_publicipaddress_info.py", + "name": "tests/integration/targets/azure_rm_account_info/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7c60893a6d181b60254e2b8e2dca0aae0c83c1f98bf2e1a6f2ab6206a222112f", + "chksum_sha256": "4a18344a391206dc34d9e73134c7e2a2815ae3cdc36cf9b6791ac19e1bc07d6a", "format": 1 }, { - "name": "plugins/modules/azure_rm_keyvault.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "4689bcd312be6a35cf796ddbb8a5594232054f9a27c638b6e843c2adaa6b55ee", + "name": "tests/integration/targets/azure_rm_managementgroup", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_postgresqlserver_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "41eccd6933ff71ce9f0bbfe939057aeea30beaf4c6e475887a7bf21df6a48f67", + "name": "tests/integration/targets/azure_rm_managementgroup/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py", + "name": "tests/integration/targets/azure_rm_managementgroup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2e8336f66de22809f5693b7c84af84f768d51992685a1daa3ef42f1416eff4ce", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_manageddisk.py", + "name": "tests/integration/targets/azure_rm_managementgroup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7fae72b490febd8d03292056a034e797aa68fb3fd52d9a849bebf3ac7b67d6d2", + "chksum_sha256": "e7fc1f0b30d75ba7b3a8f5a9a45a7703c06585edc0f3ce9231a9b2ca7a649864", "format": 1 }, { - "name": "plugins/modules/azure_rm_trafficmanagerendpoint_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "19fa3f18fc08a32e65b2dfb6c0b74a7a4827a2afcb36409214de9887899e754e", + "name": "tests/integration/targets/azure_rm_managementgroup/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_keyvaultsecret_info.py", + "name": "tests/integration/targets/azure_rm_managementgroup/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "82a8e53b9e615d6d82467cb28b4572b1dfcb128f9a4b19ccd98c613465504c48", + "chksum_sha256": "52b6ea89da7341d8977b8f1ac1fb530b48eba4831b6c5224b2c136c9bfa91ad7", "format": 1 }, { - "name": "plugins/modules/azure_rm_adapplication.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1169c9823bdf7024c552003dfbbdf1067eac2186883bf5cd7904be5d49b99352", + "name": "tests/integration/targets/azure_rm_storageaccount", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabschedule_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "775594a1c43e4e67957e6f1ef498b2fc8e04fd2d60d8215d1471084f19f9b0f6", + "name": "tests/integration/targets/azure_rm_storageaccount/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_applicationsecuritygroup_info.py", + "name": "tests/integration/targets/azure_rm_storageaccount/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "805be7606a6145a9b4c942f63a9aa46ffc10366b8e3bf2af0c64b8009d0ac9eb", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_webappslot.py", + "name": "tests/integration/targets/azure_rm_storageaccount/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d7c28a3338c7a7ecfa0da50def079ab83286aa1750aa52d13944fbac4fbf2399", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "plugins/modules/azure_rm_vmssnetworkinterface_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "968c1e5781fdca422d62eeea87dd9ac45132e5f03c7e3a91ca6b15d0683eb944", + "name": "tests/integration/targets/azure_rm_storageaccount/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualhub.py", + "name": "tests/integration/targets/azure_rm_storageaccount/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "be9396630b6c0d0cc7dae7688cd87421f4770dbba2ed92b2712761ff722ae8a5", + "chksum_sha256": "8d2c09bca13c2239c843af20b93b033b24b5abe133d4d8f9dcf08a9d1f6ad0df", "format": 1 }, { - "name": "plugins/modules/azure_rm_cognitivesearch.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "8665ce3ff083d18608c7ed9b5fb778d6248e9cfcc096b464535d041457d9af00", + "name": "tests/integration/targets/azure_rm_aks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_iotdevice.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "6d0f2a6f2f913e9d1f9547a9b601d42f5462c867480915f6ab2cc54674e6f2ec", + "name": "tests/integration/targets/azure_rm_aks/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualwan.py", + "name": "tests/integration/targets/azure_rm_aks/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4bf8e8dc2b63ad03eed2d1f50fc68f3026e00528651b132570b009e8d93232a5", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_openshiftmanagedcluster.py", + "name": "tests/integration/targets/azure_rm_aks/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1af54e81954603964c195560b80f5ae452877b564f5a86443f65b3d0f70a9e24", + "chksum_sha256": "783d6dbd1b9cc4b0543d6e96d15206283018e0c291764a2a4106e860d41cb210", "format": 1 }, { - "name": "plugins/modules/azure_rm_aksupgrade_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "e40923a0ba91ba10ec91ccd2960c60501d5e60c0287ab2578c66d756b865409f", + "name": "tests/integration/targets/azure_rm_aks/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_privatelinkservice_info.py", + "name": "tests/integration/targets/azure_rm_aks/tasks/minimal-cluster.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "02a72af00f3442e3cb5a19ba01bffc4cb2d47f646abf1a5ae0a125e80a8313ba", + "chksum_sha256": "2b2be2027bb762b22ccf731a32baf3fa8b2675369c08b76c1499b3ea10902add", "format": 1 }, { - "name": "plugins/modules/azure_rm_adpassword.py", + "name": "tests/integration/targets/azure_rm_aks/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0dca5c21f80f4d60aba58dadbfb2581c5488ce7e1c6a9c2b2bfcc03d33863689", + "chksum_sha256": "683619ec3541848983b2f513eae4d885c97d3040ac188d252aec7304c3440c0b", "format": 1 }, { - "name": "plugins/modules/azure_rm_vmbackuppolicy_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "23626d1e4710adefaddcad8cfa9f427ad1e2a9bcaff28b61004dd35b50c72e72", + "name": "tests/integration/targets/azure_rm_autoscale", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_natgateway.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "fe420872335d019070072b7541d79579eba9887f0d80e96d195ed1aaa051aea5", + "name": "tests/integration/targets/azure_rm_autoscale/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_automationrunbook_info.py", + "name": "tests/integration/targets/azure_rm_autoscale/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bf2d4439d7ef7f6b0f0ec04b345e5919fef980d15b6fb3fda111c2df53c18d16", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabschedule.py", + "name": "tests/integration/targets/azure_rm_autoscale/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "183397504be9789656fe18261844a247d3ff49eb267693819ce1f265c8d6d6d6", + "chksum_sha256": "2019d6f29a1dbe1242200ff0a0485722bc57431db8265a741c5e501cd5a920dd", "format": 1 }, { - "name": "plugins/modules/azure_rm_securitygroup.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "85ff31a12227b44cdb6c43ca52addfbfed8eeeb192f7d1747d2e66e828731c0c", + "name": "tests/integration/targets/azure_rm_autoscale/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlab_info.py", + "name": "tests/integration/targets/azure_rm_autoscale/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "84e99ed4f611c9c6d9551c77b83f0d056b68b7eb188b269860eebad6230ff299", + "chksum_sha256": "f7573c9960bd35c764fcdea5dc4542eaa1666c48dcbc33aef0c6b8e46caa23f5", "format": 1 }, { - "name": "plugins/modules/azure_rm_bastionhost.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "ade78abbea1c467a8bf4787d227a0a96979482b15d05e3dea2ede57f91ff6f7c", + "name": "tests/integration/targets/azure_rm_webappvnetconnection", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_registrationdefinition_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1c6615dbd5f7a904854e0dffad5b8ac364059a4fd93e86529a7257577423aaa6", + "name": "tests/integration/targets/azure_rm_webappvnetconnection/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_containerregistrytag_info.py", + "name": "tests/integration/targets/azure_rm_webappvnetconnection/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "99cde6ea4e4b3f5216131583a7f2ce0dc1777e836d93089733da276895c65b44", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_sqlelasticpool_info.py", + "name": "tests/integration/targets/azure_rm_webappvnetconnection/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "05959ef86783c8274fe64c2c1cec19208c37b3d038e6556ffb3a20b51813375c", + "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", "format": 1 }, { - "name": "plugins/modules/azure_rm_dnsrecordset_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "ce13d83217e276a01bc5763cdfbd131090b35c64607738dc052b7ef9d25a3068", + "name": "tests/integration/targets/azure_rm_webappvnetconnection/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_backuppolicy.py", + "name": "tests/integration/targets/azure_rm_webappvnetconnection/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "37cfea022ca13c6ea40025ae4ec9d00f9e962fba506e1a5708bc00dcfcdc9116", + "chksum_sha256": "fe11d34bfc4836a138318153cd0df0bb89f64d2d6d64f9dc7843704f1bd60760", "format": 1 }, { - "name": "plugins/modules/azure_rm_webappaccessrestriction_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c72ded459dbd8c58642c77aba5cfab56a86782f4e19958ded25f9754a32c1591", + "name": "tests/integration/targets/azure_rm_apimanagementservice", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_aksversion_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1bba9dd6d78f0d87c751b71c9ff5a29ae856cf4a3326813d8b07d9607e3af2db", + "name": "tests/integration/targets/azure_rm_apimanagementservice/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_mariadbfirewallrule.py", + "name": "tests/integration/targets/azure_rm_apimanagementservice/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6c028f0fdd933b4a02b6c92f20432fc3617072d8828898f628e02554d25c31e3", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_roleassignment.py", + "name": "tests/integration/targets/azure_rm_apimanagementservice/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "981eea70440c35499110fa7a97cc7259e7cac1ed2f790ffcb1c247a51bfa6fe3", + "chksum_sha256": "528893af1cac01f38ab277aec0138b83c74b2576464d96eb7f3da330784edaff", "format": 1 }, { - "name": "plugins/modules/azure_rm_containerregistrywebhook_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "18b7a6844956e67318fe818bdafd0c94d6631657ec33d529e721e6e21b18ed89", + "name": "tests/integration/targets/azure_rm_apimanagementservice/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_adgroup.py", + "name": "tests/integration/targets/azure_rm_apimanagementservice/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c1117a3b1c468a121dc8a76aea672cb7c839dcb094a2a7fa331f925029699666", + "chksum_sha256": "db17a45674ec599ab8fb1890903d3bc49b3ded000197dd55cc82c3017a962565", "format": 1 }, { - "name": "plugins/modules/azure_rm_keyvaultsecret.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "ace3f948b102b233b72d82b67a5b9c74d9cf650b4c04d397e427ddc15f3d45e3", + "name": "tests/integration/targets/azure_rm_availabilityset", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_loganalyticsworkspace_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b2ea8f5bf029879cd6b7367c7c07d1f638453ff39e0c9f64c04db9afa3a57f8b", + "name": "tests/integration/targets/azure_rm_availabilityset/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_mariadbserver_info.py", + "name": "tests/integration/targets/azure_rm_availabilityset/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3b836969fea8c255c6aeddca297111eef43141755a9b61677661dd581bb2f1a4", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_sqlmanagedinstance.py", + "name": "tests/integration/targets/azure_rm_availabilityset/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f022f6e315be9d163c042e9253682d15faea83c067917cba012202532f84f955", + "chksum_sha256": "5647901b6198849a4dd58b7fb51aee85b889220f80acde88cea67bffff453d8d", "format": 1 }, { - "name": "plugins/modules/azure_rm_managementgroup.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "d0c2f5410b682701b672207c321041af369dfc116f79b5531c8942f573882eb8", + "name": "tests/integration/targets/azure_rm_availabilityset/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_galleryimageversion_info.py", + "name": "tests/integration/targets/azure_rm_availabilityset/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "04410811676cb31554c731e12e6803c9e24e238645d16332971573645d01d396", + "chksum_sha256": "0d096b5b5000fd2c1c259adae048dd6ac824c2441db10e6fe352282c8bb77b8a", "format": 1 }, { - "name": "plugins/modules/azure_rm_privatednszonelink_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "93d488b4238c4631765dff43c9a6978f3bef9d8ff35294dba4f34772a85a4284", + "name": "tests/integration/targets/azure_rm_monitorlogprofile", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_privatednsrecordset.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "2b2eceb8e654a1bc257a065f5ef324c69dd6f5b1e9b0126ffd49afa77ff51367", + "name": "tests/integration/targets/azure_rm_monitorlogprofile/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_containerregistryreplication.py", + "name": "tests/integration/targets/azure_rm_monitorlogprofile/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "94d2e1237ef94377586760a091785272818db4bddc6a54d24badee82d7697437", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_trafficmanagerprofile_info.py", + "name": "tests/integration/targets/azure_rm_monitorlogprofile/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b99d27f1679a3d1fafdec74448bfdf2977930e8cef05f0b6d720971b4f6b8c8d", + "chksum_sha256": "cc618d5714ddaae8f1482cf89dcf3327cf82fa378c16f6b5cf092339927261c3", "format": 1 }, { - "name": "plugins/modules/azure_rm_privateendpointconnection_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a1c9260c99294e6c9f4579310504bf656d46b2ed16d22188859945cc53563fc0", + "name": "tests/integration/targets/azure_rm_monitorlogprofile/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_postgresqlfirewallrule_info.py", + "name": "tests/integration/targets/azure_rm_monitorlogprofile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "53187b006213c221bd5391b2b45734080afcd9e63280f4181f6355b5db7258dc", + "chksum_sha256": "71fa19924e9ae73ca408e1fccec2a768f3b2fc113158c5718b7b870c081189f1", "format": 1 }, { - "name": "plugins/modules/azure_rm_route.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f290a0e704d3225c8689ac3a7a9523facc263adace73b8193906cb5ee94bffbd", + "name": "tests/integration/targets/azure_rm_ddosprotectionplan", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_apimanagement_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "2c6da107654adcf08a5e6cf5f49473ea21b5dd86db46d4e2ff10868449108a02", + "name": "tests/integration/targets/azure_rm_ddosprotectionplan/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_image_info.py", + "name": "tests/integration/targets/azure_rm_ddosprotectionplan/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c6dfd163560a3389f0d12d364e61a5a6e6bb87f50b2fc08965b19285002b600d", + "chksum_sha256": "a66dc9e034ad04e167bd52df4f75f2bea4499b25349fc42b3c8de9e2fe806996", "format": 1 }, { - "name": "plugins/modules/azure_rm_apimanagementservice.py", + "name": "tests/integration/targets/azure_rm_ddosprotectionplan/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ff029a940b4e0f844a8623115c7b6fdcda06b8f9e192e20216f4b42d5093550a", + "chksum_sha256": "1be076424fbf717d678e202250426e9b368688f8d3029f0c5dc262b97df819af", "format": 1 }, { - "name": "plugins/modules/azure_rm_ipgroup_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "dcb8c2107767aeeae8dad3a39e68b5a1c475d9eb91e0a9c72b3276461fe0f4cd", + "name": "tests/integration/targets/azure_rm_ddosprotectionplan/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_servicebus.py", + "name": "tests/integration/targets/azure_rm_ddosprotectionplan/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f7379123759b383d1c9b39442ddff6beb7910e1bb6c68ba570a8d59eed2c6e95", + "chksum_sha256": "cac8f7d2a8403213ad252934698c6c5eef6edc0ccd0eb6c5794990e6c30f05b0", "format": 1 }, { - "name": "plugins/modules/azure_rm_privatelinkservice.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "5c56fae085180b9c34424f1cb9fce62adaac67e7107f556702f1a8b9ae00025a", + "name": "tests/integration/targets/azure_rm_eventhub", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_sqlserver.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "9b0f2f7674cdb4641de9a2b8b50cb74e91e36ce0a07e0c3a13330592574bee71", + "name": "tests/integration/targets/azure_rm_eventhub/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabcustomimage_info.py", + "name": "tests/integration/targets/azure_rm_eventhub/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "39b5c1b0361bdbb8e5782066ba0593c4e4fbcdc52243e1b2ac05e6fa8451920a", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_servicebusqueue.py", + "name": "tests/integration/targets/azure_rm_eventhub/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ba3c26da0e1437c64c3a7d945886563965b08c9fef67f099e97990ef5f50290", + "chksum_sha256": "1be076424fbf717d678e202250426e9b368688f8d3029f0c5dc262b97df819af", "format": 1 }, { - "name": "plugins/modules/azure_rm_appserviceplan.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "4230691a8fb4f96611ff509e19f598304daf58104bd7c4e01b0d3e90311a2a93", + "name": "tests/integration/targets/azure_rm_eventhub/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_privateendpoint_info.py", + "name": "tests/integration/targets/azure_rm_eventhub/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b34126d4fac558a5077869099cf1327fbecfeab36e6e34b30c4fe809d59b92de", + "chksum_sha256": "c4ef2c774f92b1d1c61c070407cb15cec4492593f03dfc095031136a6fc315e4", "format": 1 }, { - "name": "plugins/modules/azure_rm_manageddisk_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3b7b7131b77965c67a34ae4c9ddb9def5c3d30a5a76498c51580486063693f71", + "name": "tests/integration/targets/azure_rm_virtualnetworkpeering", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_mysqldatabase_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "dad732afe34bb2972eb39f7fea721d46f644e46383da754563295ebe767e4c43", + "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_resource_info.py", + "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f893b49f22424b9a2d18d9e27cf088eda9e6afa89606a337ad6771ae728be1b8", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachineimage_info.py", + "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "81e679d55f2d54420d960d51e6f0318cec3b781dd37a062df0b0ff9e1756797e", + "chksum_sha256": "ee3b904aa8ab8d0a7e47983927157b420c195fe1d8606de015158339e7824a43", "format": 1 }, { - "name": "plugins/modules/azure_rm_autoscale_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "7494564289cd93cb8e34bf724deff6fd4fb7ea335233703e1aa2a930860e1d40", + "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_privatednszonelink.py", + "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4166cc9a7e671531be63455046c657896ef9ec1e35a84f7c9bf5bc39cd50bf11", + "chksum_sha256": "2fb7b589b1c4bd6ed3778e220fe5be14d351534db03c1473e45f03fd181cf0ac", "format": 1 }, { - "name": "plugins/modules/azure_rm_containerregistryreplication_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b88adc68c275d1c2608313a8bca60f7805a473e33df0ff3b75b3ea0deb915195", + "name": "tests/integration/targets/azure_rm_resource", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_subscription_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "27171c677f1e2b5337edce509b64021d2bb2708d2b476137b3e4ac96df1631af", + "name": "tests/integration/targets/azure_rm_resource/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachinescalesetinstance.py", + "name": "tests/integration/targets/azure_rm_resource/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dcc42ecdde859c43817703218fc0582a4e44750f21b9e8ff33131266c2422916", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_webappaccessrestriction.py", + "name": "tests/integration/targets/azure_rm_resource/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a31793686f398ccb3ea7c32aad8341b808e06449bfe5ed468303d74a5406cf2a", + "chksum_sha256": "b9685232ad3eab40ee59426a3dd04a8f71719dbfa1d6becb498bb416c8d1ff1c", "format": 1 }, { - "name": "plugins/modules/azure_rm_hdinsightcluster.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3c7386b43f9f3278b17baf8b6e69bc3800389b1d84c34e49ca9e3f407d30a1eb", + "name": "tests/integration/targets/azure_rm_resource/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_sqlmanagedinstance_info.py", + "name": "tests/integration/targets/azure_rm_resource/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5b99b1ab21f96e28642c56ee1519c5a9189bc3c0b7c3beb40c11c471012dbe8d", + "chksum_sha256": "e51cbf401d0da7fb038fade492b102a3493b57c0c0e4f9ca927d726db890c4df", "format": 1 }, { - "name": "plugins/modules/azure_rm_snapshot.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "11c8c5143b3a5229dbf2615d75f3b121b4ee6f008945607d5b7656de2b0ac861", + "name": "tests/integration/targets/azure_rm_sqlmanagedinstance", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualhub_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3a9de2d79f400506887f8b86b4a8bbfffb0e0558eae4ce954d8410beff977af4", + "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_storageblob.py", + "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4c7ef09d4dd98bf61d0036a34e1d4e9f0df45c91b3d94c030e17dffa7cd91644", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_sqlserver_info.py", + "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "31710e981ec3af5a7ab221d4679e06e7d7baad4e1cca7a1e9809536cf07c8899", + "chksum_sha256": "d19280a8d5d5c2523536ea5aed2c5a14d1b19cc49f3f21974ca3e9a9921bb7cd", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualnetworkpeering.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f0ee463d7cbde4f3c704542e0ff6e8220b22f436b1014b15a355e8c832845ffd", + "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_sqlfirewallrule.py", + "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bf215ff5460bd7561374c1013e93dd13406286bedf9bb34fe5c63a423d65b996", + "chksum_sha256": "561193b252168d2eca301ab2c0f673e1a99acc2c807b9f9e8679f1e3b7058d5e", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualnetwork.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "d1f54cd77a98a82bbc32959ec20f38af893dc0a41c442c995ed64d42c53ceedc", + "name": "tests/integration/targets/azure_rm_servicebus", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_privateendpointconnection.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "9ecc4f6823fed8b227500c7714851dcc9f398424d5774bf89f8dafca9afcbef3", + "name": "tests/integration/targets/azure_rm_servicebus/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_webapp_info.py", + "name": "tests/integration/targets/azure_rm_servicebus/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ea1c14d6f336c8e2a1fd62056450a013f912f7fa3a186921548ff7ff8fb59d29", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_image.py", + "name": "tests/integration/targets/azure_rm_servicebus/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a4648f6095259498761c468442ee994954306f5a112c89ed427e4381dd1b9447", + "chksum_sha256": "923b442d786cff06e0b7a3ea4232f7bfe10835e93fb73b8df6ee997380099420", "format": 1 }, { - "name": "plugins/modules/azure_rm_routetable.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "903a9d84fb9a4c7aac19a8c54c32e414e364570fe6d02b56427b8c9a8263e979", + "name": "tests/integration/targets/azure_rm_servicebus/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabenvironment.py", + "name": "tests/integration/targets/azure_rm_servicebus/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d3900fff1e5d5b5bf9c80ac7261f044f6b0de361eb7e31f1f48d741bfab9b00a", + "chksum_sha256": "a0528bf0af2a590fe46bced0ca843722543d5f10626604a887a7c278e97c38d2", "format": 1 }, { - "name": "plugins/modules/azure_rm_recoveryservicesvault_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "0f58e9dc7ce66f1695f5038e3e9bba321e93a1e5dfd98d9a37c8d8963587078e", + "name": "tests/integration/targets/azure_rm_dnszone", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_aduser_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1d2353c2a497cc22bf6e3cd4fe2f8c52f60f4f556645ada99f014423005a0937", + "name": "tests/integration/targets/azure_rm_dnszone/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_account_info.py", + "name": "tests/integration/targets/azure_rm_dnszone/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ec36327053b86b179229d47231e614d5555b32d1c8bd6368f913743f07fa7f84", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_mysqldatabase.py", + "name": "tests/integration/targets/azure_rm_dnszone/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "69e4485770b2c839f24749ec8c5aa3ee693f8afd7ff6bd01c62c0df79275c8d6", + "chksum_sha256": "1af368a225674fcae08ea809c4dc605f03bc0334b44a9b17dfab0dfe49d93ac6", "format": 1 }, { - "name": "plugins/modules/azure_rm_notificationhub_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "07c91492398c62e54b267d583d55287c485fbe4ca5112305e0c0cb0883500e89", + "name": "tests/integration/targets/azure_rm_dnszone/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_adapplication_info.py", + "name": "tests/integration/targets/azure_rm_dnszone/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6a61a1e98531303dc5b6a44bd86ee60bb9c45aee7569a9ce92ca34e5965724af", + "chksum_sha256": "b03603dc5bddfda055b5dfa51d9c769881822cd95a0953dfe82ef9afd446926a", "format": 1 }, { - "name": "plugins/modules/azure_rm_iotdevice_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "87e22ba60e4ab700ee3bfad366690b044125b0f66091c88bc346dcc88e722262", + "name": "tests/integration/targets/azure_rm_adgroup", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_mariadbdatabase.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f8dc569f2de810f80a09d827c276f44fd85dc254766b82bed9769846f41008b6", + "name": "tests/integration/targets/azure_rm_adgroup/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_containerregistry_info.py", + "name": "tests/integration/targets/azure_rm_adgroup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b176c5d28ade7bb04fb50a82ea0c59987cc004136fcfc37a50cfa240d8c29cc3", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_postgresqlfirewallrule.py", + "name": "tests/integration/targets/azure_rm_adgroup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6a0ef8e59ec7d273bd94d6e8e40f6ffe8e0a313f8e8d912b9ecb71c5db6ea662", + "chksum_sha256": "0e90b0bd13c40122b87176faa412a83730dcc85c0060dffa0d7b0450d559ed40", "format": 1 }, { - "name": "plugins/modules/azure_rm_recoveryservicesvault.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "6e465a4c809eda3d9360a644350366ab9fd430da1720a2aa9df9407dd8e49621", + "name": "tests/integration/targets/azure_rm_adgroup/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_storageaccount.py", + "name": "tests/integration/targets/azure_rm_adgroup/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ccc3bf0ae991b6d1312489d910c777727be7c266f2c9f0c69f114ac73be0bdae", + "chksum_sha256": "716f9e691c4959caef10575abf4bf7b89fbfe795d4fb144fe4f5949fcd74f94f", "format": 1 }, { - "name": "plugins/modules/azure_rm_postgresqldatabase_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3c896791d9f215a0ab5c7cb5315bcc302392ba07eea4081b4c68cf392c7013c2", + "name": "tests/integration/targets/azure_rm_backupazurevm", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_applicationsecuritygroup.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "58f5338441960bf8824f1ed9eec52bd6c5c2ec9d8c6ab02e8a5872afd388ed39", + "name": "tests/integration/targets/azure_rm_backupazurevm/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_expressroute_info.py", + "name": "tests/integration/targets/azure_rm_backupazurevm/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5e302a549f10b209ec9b8d61051f3ddf478eea0e4d99d8eb9af1db568975994f", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_servicebustopicsubscription.py", + "name": "tests/integration/targets/azure_rm_backupazurevm/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7ffbac3a815640add669c05c8c29d78ac433ccd8e9762540746eef25457f6829", + "chksum_sha256": "91c612e6c7b96f80e7e1cede3dc0ef7431a2900356b7e85a7521e2679bfcfa49", "format": 1 }, { - "name": "plugins/modules/azure_rm_availabilityset.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "685bb7c2dfeaac6f1042b164d014064dcad6b8865cbe764da3ea9ab5f23a9a76", + "name": "tests/integration/targets/azure_rm_backupazurevm/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualhubconnection_info.py", + "name": "tests/integration/targets/azure_rm_backupazurevm/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "948b85322d1c84b4eee3709f69f2de166232472a675dd26e125c099ce13517cc", + "chksum_sha256": "4ac0d2995ac62544c567223a1e45c1b1fc568b840b645d5b42a0b41fd4df1661", "format": 1 }, { - "name": "plugins/modules/azure_rm_automationrunbook.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c257d3afae0b00ae9b09d6d5f04373def1e678ea99cd8d5778c8425d64ea0058", + "name": "tests/integration/targets/azure_rm_virtualnetworkgateway", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_storageaccount_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "27c35c2191216b55c0af4ed133c20d78f95450cfb3d7bb3605268e7db1119ad0", + "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_vmbackuppolicy.py", + "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3f0d9e125fb25e8e1fe6e575c4b4f2a51a6a16c601d52003802d6836c5215ba2", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_postgresqlconfiguration_info.py", + "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "61b7807ec717db7657e825a2c1bbd815ede63112b9ce0bd4811e1c486ef01fd3", + "chksum_sha256": "4f59a6f1fc64a79191d0110c2f203adee747fd1bb69ad631a279efa7d370eaec", "format": 1 }, { - "name": "plugins/modules/azure_rm_functionapp.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b36955b4ade5a066cf353dc80387fb9e7419fabf07664db38510b29c6931282b", + "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_postgresqlserver.py", + "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "665e6153c4700277d41a5b0b83a65601d71b3088868f8e8f93229b91a3d660b1", + "chksum_sha256": "271094dd7a4e013c0da515000e4e6257bb716cf030c89dbe37af7ca74902841d", "format": 1 }, { - "name": "plugins/modules/azure_rm_sqldatabase_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "d97f650c2b9d89769f4089c17e2d64c1ee066e5295e757119f270be7be10b25a", + "name": "tests/integration/targets/azure_rm_privateendpoint", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_apimanagement.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c56dab10921ea4cf7c3244ca5a1f0f24074b3927f0d5f42e0fd82dfd2b305fa9", + "name": "tests/integration/targets/azure_rm_privateendpoint/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_webapp.py", + "name": "tests/integration/targets/azure_rm_privateendpoint/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5d6121e5cc0c2e61329fcade74dc3092db8e6d47db080d6734b6f20e9384d50f", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabartifact_info.py", + "name": "tests/integration/targets/azure_rm_privateendpoint/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d3e22ef863e1e999fce8e6dd95bda54e1f140e0c55de17fee5ebf40a51d35b53", + "chksum_sha256": "11c35de489a3da87eb40a2ce00a80a9992fc89c3b3fdee710301ba9faacd332d", "format": 1 }, { - "name": "plugins/modules/azure_rm_registrationdefinition.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "9f987c3e5b1b9ad19919ebe6b60ef05e8bb1d14980c25931d505994f07dcb4bb", + "name": "tests/integration/targets/azure_rm_privateendpoint/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_publicipaddress.py", + "name": "tests/integration/targets/azure_rm_privateendpoint/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e2ddc75d7edca49904c6025a1e1418c0ada1ed45fd56963a8e315cf7b2074362", + "chksum_sha256": "f5c8cc29641d123e237b894acc5d13e306e61d6cc553d15561730a42e63e55fc", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "bb85cde7c504168c0013e50472526bf8170839212efce46c1ddb1a781fe1dc7c", + "name": "tests/integration/targets/azure_rm_devtestlab", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachinescalesetextension_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "0c32b71b14bbb8c0609f20d2c522792ad6f6e5bd3b8477dfadae9bb34ae61cc2", + "name": "tests/integration/targets/azure_rm_devtestlab/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_aduser.py", + "name": "tests/integration/targets/azure_rm_devtestlab/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "de250268540b1d1b14e772c77d8860a5d4942ddf58557f1858a2043be8958df2", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_aksagentpool.py", + "name": "tests/integration/targets/azure_rm_devtestlab/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "35eede66b4539d8ebfabaeba04dc70f75614d3bc94b2d19a721b527269e44404", + "chksum_sha256": "435162ac2df7aa373bc2d191a07d79c283d3891a1278b0277f85e6112b96fc03", "format": 1 }, { - "name": "plugins/modules/azure_rm_dnsrecordset.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c542f52ae53544606bc2c9e1c75ad25ebd0c8ce2d00485a43024aaa39e803adf", + "name": "tests/integration/targets/azure_rm_devtestlab/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabpolicy_info.py", + "name": "tests/integration/targets/azure_rm_devtestlab/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f22d2afaf43d8b7a581c4f05f060829090d7294d19b6824ca59e86ccae69379d", + "chksum_sha256": "17fd6c08f41838809e461f199a62e373c8bf28c5d90199bf09340ae9762dd252", "format": 1 }, { - "name": "plugins/modules/azure_rm_aksagentpoolversion_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "69fd5ecafb1b4dee2cbcb17f9b767f3fff6a9d717ca8548dec4f9735f3d213d6", + "name": "tests/integration/targets/azure_rm_registrationassignment", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_expressroute.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b7a0f0dd5862dbb3fc72329ed7c6790cc18a79e279a3e3f85896c075dda2ab1c", + "name": "tests/integration/targets/azure_rm_registrationassignment/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_resourcegroup_info.py", + "name": "tests/integration/targets/azure_rm_registrationassignment/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3336b070c7a607adde16279cdeaefe260b75c683a0ab0028b4ae6f262ebd32d8", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabvirtualmachine_info.py", + "name": "tests/integration/targets/azure_rm_registrationassignment/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ae5aa0ceace675df82f2a76e4f852a222bc892f4e406d33745d97ce848b53a4a", + "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", "format": 1 }, { - "name": "plugins/modules/azure_rm_cosmosdbaccount_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "80461bffd0ad681f97b3eaafe9db453a700658748c02114d3128b8f87f7b79f2", + "name": "tests/integration/targets/azure_rm_registrationassignment/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_sqlfirewallrule_info.py", + "name": "tests/integration/targets/azure_rm_registrationassignment/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "71e6d450073de8c90623f4048d44bd6eabaa39c36031a9beba28171a53b302cd", + "chksum_sha256": "93912c71ac63373e058c38b29f7342b6350247484a190476098c6f8c33bdae53", "format": 1 }, { - "name": "plugins/modules/azure_rm_availabilityset_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "5210c3fbf5fd2f5b702cd82ba5cf7b44604231bebbe9f00a71ee71616a8e2e6b", + "name": "tests/integration/targets/azure_rm_bastionhost", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_monitordiagnosticsetting.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a87a1032899109683876d6a6ce5eba1ee931f2c64442c0910d69242a05560b26", + "name": "tests/integration/targets/azure_rm_bastionhost/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_autoscale.py", + "name": "tests/integration/targets/azure_rm_bastionhost/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d70f6911bb558f59f68dcc61f42155c1f108526ed47e7ad3bd8f653ade1a4f8f", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabarmtemplate_info.py", + "name": "tests/integration/targets/azure_rm_bastionhost/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8f48a0242d1d4246afa2a6c856e43023daee49ffbae58db30591733304d4c9c1", + "chksum_sha256": "d57abe6f8fb0cbfb8ac22431c09126cd48bb4d2836a6d151faf92fb6fbecc6aa", "format": 1 }, { - "name": "plugins/modules/azure_rm_servicebussaspolicy.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "10d85532d9875ac3da016f15add256df6cf2cbb8a88d4a57ad316bce7df7a45c", + "name": "tests/integration/targets/azure_rm_bastionhost/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_galleryimage.py", + "name": "tests/integration/targets/azure_rm_bastionhost/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dff66513503b09036068848c5cc716f0047d15cafa59d063f833574948739db1", + "chksum_sha256": "1f4b63feed40dce0104c38b6ad43cb9e2709b25ae6642031888fcd9e6103d351", "format": 1 }, { - "name": "plugins/modules/azure_rm_dnszone.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "a9974fc3f305a83840b041b02158be7162a6c87c8fb3a3b909a2ac6255390668", + "name": "tests/integration/targets/azure_rm_virtualmachineextension", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_datalakestore.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "41a04e1e6cfc80c11eedcb66b8dd36d84a7484cd698a9e8ddc8354ecaf3a6ce7", + "name": "tests/integration/targets/azure_rm_virtualmachineextension/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_ipgroup.py", + "name": "tests/integration/targets/azure_rm_virtualmachineextension/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2aaffe067e785adc4ccb4a78a2a2d665ee6e2bd5a28b79f75e2be4695a1ce115", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_containerregistrywebhook.py", + "name": "tests/integration/targets/azure_rm_virtualmachineextension/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b911199637d90fb213eaf63e586745cfb8ab889af2f199340d0d4df59138362a", + "chksum_sha256": "0fdd66037c00d326e8724db280f591414ae437954cdedeeebb4b455784fcb4d3", "format": 1 }, { - "name": "plugins/modules/azure_rm_vpnsite.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "6d818f5250f12c9dee0a78f01f853640c25a583e022f8358355e78076c5b49b8", + "name": "tests/integration/targets/azure_rm_virtualmachineextension/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_privateendpoint.py", + "name": "tests/integration/targets/azure_rm_virtualmachineextension/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9cf71bc67a11a058b6eac5f7c06c3a003ecce968f6fe09285f43dbd81f91fdf9", + "chksum_sha256": "9e3cb1009bcddcf4db403356c71a3862d40d9978395362480795d87961229f8d", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualnetworkgateway.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "59e1d99084af0027d2c970a9e6ab6088546f4768d151a045b70615cff47b05c3", + "name": "tests/integration/targets/azure_rm_virtualmachineextension/files", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_postgresqldatabase.py", + "name": "tests/integration/targets/azure_rm_virtualmachineextension/files/test-protected-settings.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e1d1f0a296460cb6a411cc926cff5476be07b16ced01f7b9a95e64802dacf9e2", + "chksum_sha256": "436711afe43e0c31f515a016fa56e64c70f1df35502725327b8c703773d4823b", "format": 1 }, { - "name": "plugins/modules/azure_rm_iothubconsumergroup.py", + "name": "tests/integration/targets/azure_rm_virtualmachineextension/files/test-public-settings.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9d6fc8dba8ecd841d908a4b1226fa0a186c270a9eb3e8a5a054692e56c621876", + "chksum_sha256": "1063a36dc41ca530af7839c69ec22f2b92447be4c3b41e90429c970b23d9116b", "format": 1 }, { - "name": "plugins/modules/azure_rm_mysqlfirewallrule.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "8d012c884bd3e4f7880fee699b3b6c8210a1cc00c98a2166c68c8b7e6a052bc2", + "name": "tests/integration/targets/azure_rm_webappaccessrestriction", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_storageshare_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c30615415440ade0b39196ccd619a923cfce2162548c18c7edaec635f46e84e3", + "name": "tests/integration/targets/azure_rm_webappaccessrestriction/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_datalakestore_info.py", + "name": "tests/integration/targets/azure_rm_webappaccessrestriction/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "97d431f9a54962aa76ee516a8d3f0e51215e832509dc605a6bca1ede20ec9cfb", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_rediscachefirewallrule.py", + "name": "tests/integration/targets/azure_rm_webappaccessrestriction/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1dd3dd187f650d1083a42a7576b7f9a9ba1b8b5960804a0dc71e33470b2c2d73", + "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", "format": 1 }, { - "name": "plugins/modules/azure_rm_containerregistry.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "781782bcf6811e28b975d35abb3892b96dbf168421891a06e352d02ac4c00569", + "name": "tests/integration/targets/azure_rm_webappaccessrestriction/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_mysqlfirewallrule_info.py", + "name": "tests/integration/targets/azure_rm_webappaccessrestriction/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2c98b91e48ddf042f3fd0847c42b7d880fc00ed807437aa70d35ae1107ba1407", + "chksum_sha256": "23178ef47e9dbb43a51984becf44d72972a399952958fd2a76d71d6338864252", "format": 1 }, { - "name": "plugins/modules/azure_rm_trafficmanagerprofile.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "4df5198ca3361e221f283b8d1cc1d26dbb3ea265422c76ebb8d6357ab6b4d4b6", + "name": "tests/integration/targets/setup_azure", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_apimanagementservice_info.py", + "name": "tests/integration/targets/setup_azure/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5447d18ab74149d3c2b05b5cc516392d367b11e71d059d29207f9a749a334f89", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "format": 1 }, { - "name": "plugins/modules/azure_rm_aks_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "39e0afd38650dd8c802f4f405aa4f3469ddb0a741210b2c56ffe663fef2ce62c", + "name": "tests/integration/targets/azure_rm_mysqlserver", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_aksagentpool_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "92c6e3a0f537164ae87f3cf64dd071238a5c8349d7ca84a16826720fc5b82e44", + "name": "tests/integration/targets/azure_rm_mysqlserver/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_notificationhub.py", + "name": "tests/integration/targets/azure_rm_mysqlserver/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "025163a4ad192ec7b4ec14e8faf49b01e29a8a8f38cd8231aaddec9726f460bb", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_ddosprotectionplan.py", + "name": "tests/integration/targets/azure_rm_mysqlserver/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b5eb8ad5fe5b146e7b79f083f2f9747b1bc64432bc55660ac682e97e8235f023", + "chksum_sha256": "2c74420c4bc9cc5d8af14406a1d97ea762c6b8afa4de8728a4a833b2e742cf41", "format": 1 }, { - "name": "plugins/modules/azure_rm_lock.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "858b4a4357dd80fbefb9c62265d91f31019794c9077526f6703c95b5d7c077a3", + "name": "tests/integration/targets/azure_rm_mysqlserver/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_networkinterface_info.py", + "name": "tests/integration/targets/azure_rm_mysqlserver/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "22a876dccd098bc68511e639f50b08e8a50ffd1dfa24704907beb9f0a96c3029", + "chksum_sha256": "743277ee9a1eda331e62acae9a94ba4820d4bef31de88a77008d62fdda27874c", "format": 1 }, { - "name": "plugins/modules/azure_rm_adserviceprincipal.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "e141818fea5c223278d4709af5c6ae47cf4841aa0e7e823d84be8949b085d1c3", + "name": "tests/integration/targets/azure_rm_adserviceprincipal", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_appserviceplan_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "2feccbb74790330b291a4ab0f8bcf3d4ba44f5bd2c18490aff02c92f3d043e09", + "name": "tests/integration/targets/azure_rm_adserviceprincipal/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_appgateway_info.py", + "name": "tests/integration/targets/azure_rm_adserviceprincipal/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fbe1b90752ce94a33ab1c3e6771f90e4fe87d676e99819e15da631fe5fe2cea5", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_bastionhost_info.py", + "name": "tests/integration/targets/azure_rm_adserviceprincipal/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dcdf18934767abd5f6912ce0bb9cbbff6954c79fab3998fdf9ea3c75f5f9d604", + "chksum_sha256": "528893af1cac01f38ab277aec0138b83c74b2576464d96eb7f3da330784edaff", "format": 1 }, { - "name": "plugins/modules/azure_rm_virtualmachinescaleset.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "425563f892c11a2e14fe22276c308af85268b2ef1a3c2b94e779a9e18dfe7786", + "name": "tests/integration/targets/azure_rm_adserviceprincipal/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_loganalyticsworkspace.py", + "name": "tests/integration/targets/azure_rm_adserviceprincipal/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5f5d8fa3f00c30d80ce2427ccb7c9d8a00e78c255ecfc67fb1de5f37256c3418", + "chksum_sha256": "bb43a07ea959812c8beca68d9e127bd236fbe5b7a32b984b8e715c7d97126860", "format": 1 }, { - "name": "plugins/modules/azure_rm_monitorlogprofile.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "0951e10121e28230e99e7a3143ce444c9bc4cbf8b7858033c6dd5d071e1ac579", + "name": "tests/integration/targets/azure_rm_containerregistry", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_privatednszone.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c4def272c347cc85f0e108b4392b69eabd6e9caf432cbb84b2acc902bd8a3f34", + "name": "tests/integration/targets/azure_rm_containerregistry/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "plugins/modules/azure_rm_diskencryptionset_info.py", + "name": "tests/integration/targets/azure_rm_containerregistry/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "586109c40b10714b5280368db2802fca8d4fc87f797e2b0d5084bb5e7a4df3df", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "plugins/modules/azure_rm_devtestlabpolicy.py", + "name": "tests/integration/targets/azure_rm_containerregistry/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0146075d793b46427030cb705c7db55a93b6402afe9401b04dfe56a1434dee26", + "chksum_sha256": "ec1ff0ecb096def7880d4a1aab74cae1ee3e46dbdba9df7f476b7311ee64f2ab", "format": 1 }, { - "name": "plugins/modules/azure_rm_monitordiagnosticsetting_info.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3fa25b176b8c073c9435901c2c8455577e64a998c71b5c6a472ae1044f48bed9", + "name": "tests/integration/targets/azure_rm_containerregistry/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "azure-pipelines.yml", + "name": "tests/integration/targets/azure_rm_containerregistry/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1f55cf75a25502f8322df2fc8640e52f85fed4459b8c26fee3c75295f9c45552", + "chksum_sha256": "7eab7dde3b4ad416e882a673e1b671770c760c1d2ff97f9c21606a24bb3a7540", "format": 1 }, { - "name": "tests", + "name": "tests/integration/targets/azure_rm_keyvault", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/utils", + "name": "tests/integration/targets/azure_rm_keyvault/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/utils/ado", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/azure_rm_keyvault/meta/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/utils/ado/ado.sh", + "name": "tests/integration/targets/azure_rm_keyvault/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8d43591bdea6cbc13771abd458687415cadeb81242b5c706356e4554fb445e32", + "chksum_sha256": "726101a2dd7238a8ff7f94fec489e5fcfd8bb0db10ecd074fa0686b2eb9d6d24", "format": 1 }, { - "name": "tests/utils/shippable", + "name": "tests/integration/targets/azure_rm_keyvault/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/utils/shippable/timing.py", + "name": "tests/integration/targets/azure_rm_keyvault/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e4906097dcc02406930229bf0a026f667327fbe11ea6b9763bc76b4c3e98be29", + "chksum_sha256": "de8f88e9575ad797145737f6116de12c7443c09d4b9d6488a0d8a77747d564cf", "format": 1 }, { - "name": "tests/utils/shippable/timing.sh", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f3f3cc03a997cdba719b0542fe668fc612451841cbe840ab36865f30aa54a1bd", + "name": "tests/integration/targets/azure_rm_virtualnetwork", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/utils/shippable/check_matrix.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f4a38ad2db66b272075c37e9cca352fc7d5b69fe19e32adec0cdd74f91586fe6", + "name": "tests/integration/targets/azure_rm_virtualnetwork/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/utils/shippable/sanity.sh", + "name": "tests/integration/targets/azure_rm_virtualnetwork/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1cd365c5bad1facb7e98cad97a20e34231f49fca169653ccd7d34bd955bd88f6", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/utils/shippable/cloud.sh", + "name": "tests/integration/targets/azure_rm_virtualnetwork/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "99db6946e47cf9e49ab2fccbe0aca8ffc9aaa0918fdc9e3ef543601c55a98713", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "tests/utils/shippable/shippable.sh", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "829380ef8b40f42a82696ada1168318856596f4e943bbb9a4f5cd6130bbce2af", + "name": "tests/integration/targets/azure_rm_virtualnetwork/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/utils/shippable/azure.sh", + "name": "tests/integration/targets/azure_rm_virtualnetwork/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "99db6946e47cf9e49ab2fccbe0aca8ffc9aaa0918fdc9e3ef543601c55a98713", + "chksum_sha256": "e46b1abb1ab82874622d1821b564cee555be16ced454a9723f3cff45dcb5948c", "format": 1 }, { - "name": "tests/config.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "410698cc625c851ec21f2ef8ea020cf7a353590d10a995a3c57eb52d4d8065fb", + "name": "tests/integration/targets/azure_rm_sqlserver", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/lint", + "name": "tests/integration/targets/azure_rm_sqlserver/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/lint/ignore-lint.txt", + "name": "tests/integration/targets/azure_rm_sqlserver/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bea1480e79bf52af44c7d7b2b112aead789a54696c6ef6469f2dcd710ad2a47f", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/azure_rm_sqlserver/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b497f92848d198221058a5f5aa42e37dc513f9d2a64f54b2ddc9029b80ab7219", "format": 1 }, { - "name": "tests/integration/targets", + "name": "tests/integration/targets/azure_rm_sqlserver/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlserver", + "name": "tests/integration/targets/azure_rm_sqlserver/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4b9b3011d1cd399cf58fc8749d467300f6a19f2105a9455c6cc385c2468c1b02", + "format": 1 + }, + { + "name": "tests/integration/targets/azure_rm_roledefinition", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlserver/meta", + "name": "tests/integration/targets/azure_rm_roledefinition/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlserver/meta/main.yml", + "name": "tests/integration/targets/azure_rm_roledefinition/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlserver/aliases", + "name": "tests/integration/targets/azure_rm_roledefinition/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b497f92848d198221058a5f5aa42e37dc513f9d2a64f54b2ddc9029b80ab7219", + "chksum_sha256": "cc618d5714ddaae8f1482cf89dcf3327cf82fa378c16f6b5cf092339927261c3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlserver/tasks", + "name": "tests/integration/targets/azure_rm_roledefinition/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlserver/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_roledefinition/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4b9b3011d1cd399cf58fc8749d467300f6a19f2105a9455c6cc385c2468c1b02", + "chksum_sha256": "821801ed627b59f6418e9073527531be7f66a7e6069cfd50df025e197af04485", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_image", + "name": "tests/integration/targets/azure_rm_securitygroup", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_image/meta", + "name": "tests/integration/targets/azure_rm_securitygroup/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_image/meta/main.yml", + "name": "tests/integration/targets/azure_rm_securitygroup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_image/aliases", + "name": "tests/integration/targets/azure_rm_securitygroup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fca45b39c1e6a21b8fb8e1b6c8f5954d8accf0bc6fa436361d75b014b36a8fd6", + "chksum_sha256": "a390a5b729f05cbb0f6d91d7d663389c81a571a34bd2e931dc56fcdaee025754", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_image/tasks", + "name": "tests/integration/targets/azure_rm_securitygroup/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_image/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_securitygroup/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f15012224b91b0dcb340a2dfcd3d360a36bf2ed291b88a4206914ac5db295466", + "chksum_sha256": "09c95d217158fb888e0794bbfa0c39a501ace1c0686f0ee4c320bb0687e71bee", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_managementgroup", + "name": "tests/integration/targets/azure_rm_backuppolicy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_managementgroup/meta", + "name": "tests/integration/targets/azure_rm_backuppolicy/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_managementgroup/meta/main.yml", + "name": "tests/integration/targets/azure_rm_backuppolicy/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_managementgroup/aliases", + "name": "tests/integration/targets/azure_rm_backuppolicy/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e7fc1f0b30d75ba7b3a8f5a9a45a7703c06585edc0f3ce9231a9b2ca7a649864", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_managementgroup/tasks", + "name": "tests/integration/targets/azure_rm_backuppolicy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_managementgroup/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_backuppolicy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "52b6ea89da7341d8977b8f1ac1fb530b48eba4831b6c5224b2c136c9bfa91ad7", + "chksum_sha256": "26b1ed48d843898e1dc63a09a119c74ee83613ed2f0066e2971f3056eda0ee88", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszonelink", + "name": "tests/integration/targets/azure_rm_sshpublickey", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszonelink/meta", + "name": "tests/integration/targets/azure_rm_sshpublickey/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszonelink/meta/main.yml", + "name": "tests/integration/targets/azure_rm_sshpublickey/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszonelink/aliases", + "name": "tests/integration/targets/azure_rm_sshpublickey/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszonelink/tasks", + "name": "tests/integration/targets/azure_rm_sshpublickey/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszonelink/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_sshpublickey/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fe73403f7245a8d8d762b068cc62624999c45eea47a08d7c370685370d73a216", + "chksum_sha256": "56333300b98e7c24a4c8361ae59287062db7667a8d70fa9d9982fae2f6bb145c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_deployment", + "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_deployment/meta", + "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_deployment/meta/main.yml", + "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_deployment/aliases", + "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "11d8df93f7c7fb0bd35df23550ce55cea64300cbd7b3a1282927d49c53f53951", + "chksum_sha256": "11c35de489a3da87eb40a2ce00a80a9992fc89c3b3fdee710301ba9faacd332d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_deployment/tasks", + "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_deployment/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7d55d04096bc98a7e4b9423ce7a67bd90ff057d8f2597489e018095d8c7747b0", + "chksum_sha256": "5118cdd6e0f6afa96aec75b0208d11b45f3c8c533c77df13ab117b5292331094", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hostgroup", + "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hostgroup/meta", + "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hostgroup/meta/main.yml", + "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hostgroup/aliases", + "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", + "chksum_sha256": "20ed61d096d02ba8d900ce019b1762e22889c502a78e1d8716fe4a78ed8c5315", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hostgroup/tasks", + "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hostgroup/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a11e09783bbddbc59c9ddb098a44d5e17aaac05fec0334ef225dd2d301651e17", + "chksum_sha256": "efdfeffba2b8c08435fb50245a8c29ee7ac7273a20a631abf82729ae5741e6ed", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adapplication", + "name": "tests/integration/targets/azure_rm_appserviceplan", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adapplication/meta", + "name": "tests/integration/targets/azure_rm_appserviceplan/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adapplication/meta/main.yml", + "name": "tests/integration/targets/azure_rm_appserviceplan/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adapplication/aliases", + "name": "tests/integration/targets/azure_rm_appserviceplan/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0e90b0bd13c40122b87176faa412a83730dcc85c0060dffa0d7b0450d559ed40", + "chksum_sha256": "3d8b505b037b869206fe23e768d9d42e48dc8db7c83ac3023ec1be689261f907", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adapplication/tasks", + "name": "tests/integration/targets/azure_rm_appserviceplan/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adapplication/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_appserviceplan/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b35d1ada403add1e0a23a265f11a6395959c863e48579a060b40ed7f4e2b8b66", + "chksum_sha256": "f3fd1981d472300a8b2044ffbd73e928a089c2d81b3c09d7d5dff19c5d6cd544", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitorlogprofile", + "name": "tests/integration/targets/azure_rm_apimanagement", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitorlogprofile/meta", + "name": "tests/integration/targets/azure_rm_apimanagement/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitorlogprofile/meta/main.yml", + "name": "tests/integration/targets/azure_rm_apimanagement/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitorlogprofile/aliases", + "name": "tests/integration/targets/azure_rm_apimanagement/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cc618d5714ddaae8f1482cf89dcf3327cf82fa378c16f6b5cf092339927261c3", + "chksum_sha256": "592e63285615e1fe4768ff5027ae6a96e4dea5c875e1127e14c393cfacbc44fb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitorlogprofile/tasks", + "name": "tests/integration/targets/azure_rm_apimanagement/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitorlogprofile/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_apimanagement/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "71fa19924e9ae73ca408e1fccec2a768f3b2fc113158c5718b7b870c081189f1", + "chksum_sha256": "169f954c7d4a5a375a80f3d3ddd3d224713bc9dd61d2d732247c752d1bc4297f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineextension", + "name": "tests/integration/targets/azure_rm_adpassword", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineextension/meta", + "name": "tests/integration/targets/azure_rm_adpassword/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineextension/meta/main.yml", + "name": "tests/integration/targets/azure_rm_adpassword/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineextension/aliases", + "name": "tests/integration/targets/azure_rm_adpassword/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0fdd66037c00d326e8724db280f591414ae437954cdedeeebb4b455784fcb4d3", + "chksum_sha256": "0e90b0bd13c40122b87176faa412a83730dcc85c0060dffa0d7b0450d559ed40", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineextension/tasks", + "name": "tests/integration/targets/azure_rm_adpassword/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineextension/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_adpassword/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9e3cb1009bcddcf4db403356c71a3862d40d9978395362480795d87961229f8d", + "chksum_sha256": "b611592114d3a2e8e6da4246fb2408dd7e24ebf1950e63916af2fc2c7d1b8ffb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineextension/files", + "name": "tests/integration/targets/azure_rm_postgresqlflexibleserver", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineextension/files/test-public-settings.json", + "name": "tests/integration/targets/azure_rm_postgresqlflexibleserver/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/azure_rm_postgresqlflexibleserver/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1063a36dc41ca530af7839c69ec22f2b92447be4c3b41e90429c970b23d9116b", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineextension/files/test-protected-settings.json", + "name": "tests/integration/targets/azure_rm_postgresqlflexibleserver/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "436711afe43e0c31f515a016fa56e64c70f1df35502725327b8c703773d4823b", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationrunbook", + "name": "tests/integration/targets/azure_rm_postgresqlflexibleserver/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationrunbook/meta", + "name": "tests/integration/targets/azure_rm_postgresqlflexibleserver/tasks/main.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b6fa3f158220b7cd8d38e7a773ee15e4f9781e627df4e3a209142f6c430414f1", + "format": 1 + }, + { + "name": "tests/integration/targets/azure_rm_virtualmachineimage_info", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationrunbook/meta/main.yml", + "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationrunbook/aliases", + "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "522c2e1148926193596b31fa7cf086b9f57e17c7028abc638a2b6f5bb9269850", + "chksum_sha256": "8eb6da86566844e8278692f99177c27f5e17dfc808484e9168d842ce4ea822b2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationrunbook/tasks", + "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationrunbook/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a1368da2abfb774ea5e3fd1a9238e9fbadbbc6fb1a93c00685bdc1d966e401b4", + "chksum_sha256": "c1027dcaf3ce2f749a07c7b78ee56ff713901f0fa792e08ebfc2c31671426a1c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_iothub", + "name": "tests/integration/targets/azure_rm_containerregistrytag", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_iothub/meta", + "name": "tests/integration/targets/azure_rm_containerregistrytag/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_iothub/meta/main.yml", + "name": "tests/integration/targets/azure_rm_containerregistrytag/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_iothub/aliases", + "name": "tests/integration/targets/azure_rm_containerregistrytag/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8d4097a5a2543084f3eea11259e299ba87ade8dc8995e5745358931356bee79f", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_iothub/tasks", + "name": "tests/integration/targets/azure_rm_containerregistrytag/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_iothub/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_containerregistrytag/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1e5e67ce46e6ae0d5e38dbc0526e3140c3f1f3d978883736c4c84e0732042dbf", + "chksum_sha256": "c3f1c91c39a8986e9aaaaf4e0f2bd84796f20ede51d7868e74a37a7839d1759d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultkey", + "name": "tests/integration/targets/azure_rm_mariadbserver", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultkey/meta", + "name": "tests/integration/targets/azure_rm_mariadbserver/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultkey/meta/main.yml", + "name": "tests/integration/targets/azure_rm_mariadbserver/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultkey/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "36614727374728e26b5686e9fac66641e5b9c268b6945f2dcd1b4a9c4d2232c3", - "format": 1 - }, - { - "name": "tests/integration/targets/azure_rm_keyvaultkey/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/azure_rm_keyvaultkey/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_mariadbserver/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9a2de112faff356ffd7328876a499692420544b0558695813205740517ddda32", + "chksum_sha256": "0f1123b3696957f55774d4316a4461182998975a0db1f960ef289b20b5e926c7", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultkey/lookup_plugins", + "name": "tests/integration/targets/azure_rm_mariadbserver/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultkey/lookup_plugins/azure_service_principal_attribute.py", + "name": "tests/integration/targets/azure_rm_mariadbserver/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ecf5403290d75ebf93dd07c1a0d1ec251482cde7952d5fc4c1f51ecde936e804", + "chksum_sha256": "b829d34d571be3c848284902c00755a940e2a629115fbbd3a78af1ce018a0ede", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnszone", + "name": "tests/integration/targets/azure_rm_hdinsightcluster", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnszone/meta", + "name": "tests/integration/targets/azure_rm_hdinsightcluster/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnszone/meta/main.yml", + "name": "tests/integration/targets/azure_rm_hdinsightcluster/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnszone/aliases", + "name": "tests/integration/targets/azure_rm_hdinsightcluster/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1af368a225674fcae08ea809c4dc605f03bc0334b44a9b17dfab0dfe49d93ac6", + "chksum_sha256": "dffdf5ca6061cf1a43744d6b7e0bb18a4020eed3f693702082b2314f982c65a6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnszone/tasks", + "name": "tests/integration/targets/azure_rm_hdinsightcluster/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnszone/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_hdinsightcluster/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b03603dc5bddfda055b5dfa51d9c769881822cd95a0953dfe82ef9afd446926a", + "chksum_sha256": "2a0464f133b840983fad3fa552279ac8aca4a07023877e84bd273e8bde440f65", "format": 1 }, { @@ -2892,4385 +2892,4525 @@ "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roledefinition", + "name": "tests/integration/targets/azure_rm_vmbackuppolicy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roledefinition/meta", + "name": "tests/integration/targets/azure_rm_vmbackuppolicy/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roledefinition/meta/main.yml", + "name": "tests/integration/targets/azure_rm_vmbackuppolicy/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roledefinition/aliases", + "name": "tests/integration/targets/azure_rm_vmbackuppolicy/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cc618d5714ddaae8f1482cf89dcf3327cf82fa378c16f6b5cf092339927261c3", + "chksum_sha256": "923b442d786cff06e0b7a3ea4232f7bfe10835e93fb73b8df6ee997380099420", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roledefinition/tasks", + "name": "tests/integration/targets/azure_rm_vmbackuppolicy/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roledefinition/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_vmbackuppolicy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "821801ed627b59f6418e9073527531be7f66a7e6069cfd50df025e197af04485", + "chksum_sha256": "e990393d47f344ab98b507415273d6ec89117b52b4feba04783ab07d792e7243", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhubconnection", + "name": "tests/integration/targets/azure_rm_rediscache", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhubconnection/meta", + "name": "tests/integration/targets/azure_rm_rediscache/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhubconnection/meta/main.yml", + "name": "tests/integration/targets/azure_rm_rediscache/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhubconnection/aliases", + "name": "tests/integration/targets/azure_rm_rediscache/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", + "chksum_sha256": "5ba0bf8a7bf29813d54b53fd7c3e65698ee5f802eb2ccf76c1707680acc07f17", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhubconnection/tasks", + "name": "tests/integration/targets/azure_rm_rediscache/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhubconnection/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_rediscache/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2d37e8ad199f86a0ff21d8af2a5eb5555b9cc8f8f2ecd7b6597b0c9645696050", + "chksum_sha256": "60978e58b15da724fb1f16447071e7b33add290150dfbdd4173900c4edda9a91", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_azurefirewall", + "name": "tests/integration/targets/azure_rm_cognitivesearch", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_azurefirewall/meta", + "name": "tests/integration/targets/azure_rm_cognitivesearch/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_azurefirewall/meta/main.yml", + "name": "tests/integration/targets/azure_rm_cognitivesearch/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_azurefirewall/aliases", + "name": "tests/integration/targets/azure_rm_cognitivesearch/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c00350cca0b02532fa9ae31b5fdf0d5b963615b521197b71ac4cc024aac9d037", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_azurefirewall/tasks", + "name": "tests/integration/targets/azure_rm_cognitivesearch/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_azurefirewall/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_cognitivesearch/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "99e09441ca9bb38a0844a3421ebdd6d6e496690d6aa853f111ec79d73108bef1", + "chksum_sha256": "e3712847b582b6a3a3f461055963ce51034e160b1e174d06b8b8f6eeecd4bc19", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webapp", + "name": "tests/integration/targets/azure_rm_virtualmachinesize_info", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webapp/meta", + "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webapp/meta/main.yml", + "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webapp/aliases", + "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "75b6fa7694979e088e4b068016381f37a603045a395e3b8c660032f4008257d5", + "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webapp/tasks", + "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webapp/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9c075ffff039ce42e02bf19ae7081bbfaa590fe56d36c10fe5552ade5e8d9964", + "chksum_sha256": "6684f96227d75c363a588e1be85cc7ce53025d7e13844638d100781003901db6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aduser", + "name": "tests/integration/targets/azure_rm_cosmosdbaccount", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aduser/meta", + "name": "tests/integration/targets/azure_rm_cosmosdbaccount/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aduser/meta/main.yml", + "name": "tests/integration/targets/azure_rm_cosmosdbaccount/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aduser/aliases", + "name": "tests/integration/targets/azure_rm_cosmosdbaccount/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1658975f0508387cde4cda499d7eb9524e31bc2f02cc49d6483d7e210d991234", + "chksum_sha256": "d9b370414fbcd599ba1e1fa7adb52887e0df75d2ffce2a609bd5af743b02f600", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aduser/tasks", + "name": "tests/integration/targets/azure_rm_cosmosdbaccount/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aduser/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_cosmosdbaccount/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5d5d5fecd3bd106cc7e4ea4412f28e287297cbd7f7c5699f4ed5e27c60d25610", + "chksum_sha256": "e44d0c16980fee5a6cca7dc10c26e4bb487b761eb6aa87c5cee17e527c37453d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkpeering", + "name": "tests/integration/targets/azure_rm_publicipaddress", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/meta", + "name": "tests/integration/targets/azure_rm_publicipaddress/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/meta/main.yml", + "name": "tests/integration/targets/azure_rm_publicipaddress/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/aliases", + "name": "tests/integration/targets/azure_rm_publicipaddress/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ee3b904aa8ab8d0a7e47983927157b420c195fe1d8606de015158339e7824a43", + "chksum_sha256": "ed3159c0b56e6e42548ed58456e5304d48aea0b4e3a0999591f863ae79b225ba", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/tasks", + "name": "tests/integration/targets/azure_rm_publicipaddress/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkpeering/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_publicipaddress/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2fb7b589b1c4bd6ed3778e220fe5be14d351534db03c1473e45f03fd181cf0ac", + "chksum_sha256": "0240ae96de6dabce7cd47a7793fb7a263717ea1b2e28423f47ba0c75333ed8cd", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cosmosdbaccount", + "name": "tests/integration/targets/azure_rm_privatelinkservice", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cosmosdbaccount/meta", + "name": "tests/integration/targets/azure_rm_privatelinkservice/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cosmosdbaccount/meta/main.yml", + "name": "tests/integration/targets/azure_rm_privatelinkservice/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cosmosdbaccount/aliases", + "name": "tests/integration/targets/azure_rm_privatelinkservice/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d9b370414fbcd599ba1e1fa7adb52887e0df75d2ffce2a609bd5af743b02f600", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cosmosdbaccount/tasks", + "name": "tests/integration/targets/azure_rm_privatelinkservice/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cosmosdbaccount/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_privatelinkservice/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e44d0c16980fee5a6cca7dc10c26e4bb487b761eb6aa87c5cee17e527c37453d", + "chksum_sha256": "26d7dc158898d9dbc017b66108ef335ff0b4a5ba01d2566cecbec6ad767763be", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loadbalancer", + "name": "tests/integration/targets/azure_rm_storageshare", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loadbalancer/meta", + "name": "tests/integration/targets/azure_rm_storageshare/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loadbalancer/meta/main.yml", + "name": "tests/integration/targets/azure_rm_storageshare/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loadbalancer/aliases", + "name": "tests/integration/targets/azure_rm_storageshare/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "923b442d786cff06e0b7a3ea4232f7bfe10835e93fb73b8df6ee997380099420", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loadbalancer/tasks", + "name": "tests/integration/targets/azure_rm_storageshare/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loadbalancer/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_storageshare/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6b6dc390a0291155225b4305560c255bf3a36be60542213e2ad2fcc6fb9daf94", + "chksum_sha256": "8428a40d80a569d0c5ac929641e4befc59b86cf7c7cc4da72add3b5eb4570202", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks", + "name": "tests/integration/targets/azure_rm_loadbalancer", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/meta", + "name": "tests/integration/targets/azure_rm_loadbalancer/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/meta/main.yml", + "name": "tests/integration/targets/azure_rm_loadbalancer/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/aliases", + "name": "tests/integration/targets/azure_rm_loadbalancer/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ea124e6a615561c87b4dd84d829b1eb1d2bd1658d1caf6211019eeda3ffc8136", + "chksum_sha256": "923b442d786cff06e0b7a3ea4232f7bfe10835e93fb73b8df6ee997380099420", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/tasks", + "name": "tests/integration/targets/azure_rm_loadbalancer/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "8e23e36b5f9691d484992b8472b963aa9265f9e12c2b5eace4da7b532d66c3db", - "format": 1 - }, - { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/tasks/test_async.yml", + "name": "tests/integration/targets/azure_rm_loadbalancer/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c7047ff5651f3faf6ac16b87e5434fd16dae5a620b45ed55723a208b27b9d4bc", + "chksum_sha256": "6b6dc390a0291155225b4305560c255bf3a36be60542213e2ad2fcc6fb9daf94", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/tasks/test_shared.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "347f0eb7c19d4e9cb7070d4eff76a456f649df4792a590d75b0258643d1c4282", + "name": "tests/integration/targets/azure_rm_virtualhubconnection", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/defaults", + "name": "tests/integration/targets/azure_rm_virtualhubconnection/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/defaults/main.yml", + "name": "tests/integration/targets/azure_rm_virtualhubconnection/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e74506a8cfbf91887befefae0b179455f0071b5d904b30c00b67897373123b23", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/templates", + "name": "tests/integration/targets/azure_rm_virtualhubconnection/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", + "format": 1 + }, + { + "name": "tests/integration/targets/azure_rm_virtualhubconnection/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_multiplemanageddisks/templates/disk_config.j2", + "name": "tests/integration/targets/azure_rm_virtualhubconnection/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d52e27205862487e08375c08ac7c8aa27c059db63c3fb83ebb8dd8eb0e7e11f6", + "chksum_sha256": "2d37e8ad199f86a0ff21d8af2a5eb5555b9cc8f8f2ecd7b6597b0c9645696050", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualwan", + "name": "tests/integration/targets/azure_rm_privatednszonelink", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualwan/meta", + "name": "tests/integration/targets/azure_rm_privatednszonelink/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualwan/meta/main.yml", + "name": "tests/integration/targets/azure_rm_privatednszonelink/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualwan/aliases", + "name": "tests/integration/targets/azure_rm_privatednszonelink/aliases", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualwan/tasks", + "name": "tests/integration/targets/azure_rm_privatednszonelink/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualwan/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_privatednszonelink/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9ab3ddca93908d5c847cccd627d21e6dd17c1d4c24cfe0f06331431717be8bfd", + "chksum_sha256": "fe73403f7245a8d8d762b068cc62624999c45eea47a08d7c370685370d73a216", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster", + "name": "tests/integration/targets/azure_rm_virtualmachinescaleset", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/meta", + "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/meta/main.yml", + "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/aliases", + "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "20ed61d096d02ba8d900ce019b1762e22889c502a78e1d8716fe4a78ed8c5315", + "chksum_sha256": "5510a946bf7e1d1ad196eaa73474176b122ae491702a99f9160ad1d554fc08bf", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks", + "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3265ddca3e6f3be968be4b2d516c453c1c305f010ef7f1ab4deb0d9d70bb03eb", + "chksum_sha256": "2b560766f54992fab349101fb4528f9bf12022337f573ad7f8bc3a9b80e9dff7", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_trafficmanagerprofile", + "name": "tests/integration/targets/azure_rm_natgateway", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/meta", + "name": "tests/integration/targets/azure_rm_natgateway/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/meta/main.yml", + "name": "tests/integration/targets/azure_rm_natgateway/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/aliases", + "name": "tests/integration/targets/azure_rm_natgateway/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b34b028873420b7fdba3b5e4f0b3a1283d3879fcf1ee2d91dbe8a732651ca04a", + "chksum_sha256": "21442459796e3c03ab3c6461c8251810f5545ff2320c4c814cce8b8c520e615c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/tasks", + "name": "tests/integration/targets/azure_rm_natgateway/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_natgateway/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d48b39bfcd3c3f106af3c9eedcc4005c40eb6642ce232ae4f834c93875ee74e9", + "chksum_sha256": "b0c6592fbe22d552060e636b988771db2fe2e14e50462d4ab5589a8f3f4f8e9f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_natgateway", + "name": "tests/integration/targets/azure_rm_deployment", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_natgateway/meta", + "name": "tests/integration/targets/azure_rm_deployment/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_natgateway/meta/main.yml", + "name": "tests/integration/targets/azure_rm_deployment/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_natgateway/aliases", + "name": "tests/integration/targets/azure_rm_deployment/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "21442459796e3c03ab3c6461c8251810f5545ff2320c4c814cce8b8c520e615c", + "chksum_sha256": "11d8df93f7c7fb0bd35df23550ce55cea64300cbd7b3a1282927d49c53f53951", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_natgateway/tasks", + "name": "tests/integration/targets/azure_rm_deployment/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_natgateway/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_deployment/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b0c6592fbe22d552060e636b988771db2fe2e14e50462d4ab5589a8f3f4f8e9f", + "chksum_sha256": "7d55d04096bc98a7e4b9423ce7a67bd90ff057d8f2597489e018095d8c7747b0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway", + "name": "tests/integration/targets/azure_rm_containerinstance", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway/meta", + "name": "tests/integration/targets/azure_rm_containerinstance/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway/meta/main.yml", + "name": "tests/integration/targets/azure_rm_containerinstance/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway/aliases", + "name": "tests/integration/targets/azure_rm_containerinstance/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "21442459796e3c03ab3c6461c8251810f5545ff2320c4c814cce8b8c520e615c", + "chksum_sha256": "059ec72ab54682d34b109880aa48f5b5b702d120042153371442c7293c011f31", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway/tasks", + "name": "tests/integration/targets/azure_rm_containerinstance/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_containerinstance/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7d8ffa4ec62e8b5bcf85c4c36004a71daf4b8bf455238a1b6a8a1749fd64bd4d", + "chksum_sha256": "d5d577eb39a4533fea27bd3240b4ffaa278f64b5f56b5c6375c0d1e73b7ba382", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway/files", + "name": "tests/integration/targets/azure_rm_virtualwan", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway/files/cert3b64.txt", + "name": "tests/integration/targets/azure_rm_virtualwan/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/azure_rm_virtualwan/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1375dc6f493fb760c6087c4cdd62c4ea898887070ad17dc84196b3d6ed0545ec", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway/files/cert1.txt", + "name": "tests/integration/targets/azure_rm_virtualwan/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7637ce7f36cca366294688f612f6456714088cca19583ae7e9475e572d85f4f5", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appgateway/files/cert2.txt", + "name": "tests/integration/targets/azure_rm_virtualwan/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/azure_rm_virtualwan/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e4dc34faa2e8e94cd385be73c33a849f452dd57d061a8aec118e6d391e46bbc0", + "chksum_sha256": "9ab3ddca93908d5c847cccd627d21e6dd17c1d4c24cfe0f06331431717be8bfd", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinescaleset", + "name": "tests/integration/targets/inventory_azure", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/meta", + "name": "tests/integration/targets/inventory_azure/playbooks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/meta/main.yml", + "name": "tests/integration/targets/inventory_azure/playbooks/vars.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "23fff20fb969471888915a24760b7a90723a30e3e0e6b7c7745864470c898027", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/aliases", + "name": "tests/integration/targets/inventory_azure/playbooks/create_inventory_config.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5510a946bf7e1d1ad196eaa73474176b122ae491702a99f9160ad1d554fc08bf", + "chksum_sha256": "96709396441733bc7e0001d045f1f825170489df8eae9cfdb677722f70e034be", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/inventory_azure/playbooks/setup.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e95740d1317dda6c7a610a482d33b29e2035293ff74e10a2bcc0f2997ba85430", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml", + "name": "tests/integration/targets/inventory_azure/playbooks/test_inventory.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "088fc01b37760ce34fafbf49d9cad124a44df1c8390c23c58480447c275bb9a5", + "chksum_sha256": "ec64466973b4afce9659407d0b56ac133028b3965a06bc27ebbe227cd5da8b11", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datalakestore", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/inventory_azure/playbooks/empty_inventory_config.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "86545d143dd65f74a63218943018bfad054837e6c813fd396442957c89e87a62", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datalakestore/meta", + "name": "tests/integration/targets/inventory_azure/playbooks/teardown.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1f44c8ef223d0219855c453cd859b44b7cd4b2fa10fb1f8cacac75e020975fc8", + "format": 1 + }, + { + "name": "tests/integration/targets/inventory_azure/templates", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datalakestore/meta/main.yml", + "name": "tests/integration/targets/inventory_azure/templates/basic.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "3f99d3d1c0b4f896b1f43477667fc744c2cd2d38471c5bbc9287773b57682628", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datalakestore/aliases", + "name": "tests/integration/targets/inventory_azure/templates/basic2.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", + "chksum_sha256": "758f6dfaa158a3601eb9cd986357f1a40a04071ad62f3ba613002ffde00d6018", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datalakestore/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/inventory_azure/runme.sh", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "203fe16581a305486f7d5a2feafad324ed5515a96c26b4f4d84ab34a1cdcb6a3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datalakestore/tasks/main.yml", + "name": "tests/integration/targets/inventory_azure/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2d7c9df4757ded6e5d8fdb419854a55eb85d7782884e81548d299a795998daa6", + "chksum_sha256": "e2e2f39006f1e6b83660c469a9c29e1dfb17b99cca9caa124626e14cd0658a0b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_functionapp", + "name": "tests/integration/targets/inventory_azure/test.azure_rm.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "format": 1 + }, + { + "name": "tests/integration/targets/azure_rm_trafficmanagerprofile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_functionapp/meta", + "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_functionapp/meta/main.yml", + "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_functionapp/aliases", + "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", + "chksum_sha256": "b34b028873420b7fdba3b5e4f0b3a1283d3879fcf1ee2d91dbe8a732651ca04a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_functionapp/tasks", + "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_functionapp/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_trafficmanagerprofile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a5d18ded0b871348c349b69152916bc7b243670fdc7ec9a2f8ab479ce589e390", + "chksum_sha256": "65beb0620dd28c47587519e4bb5eed48d9e4b66979521bc9cc88153702829b5e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subnet", + "name": "tests/integration/targets/azure_rm_image", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subnet/meta", + "name": "tests/integration/targets/azure_rm_image/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subnet/meta/main.yml", + "name": "tests/integration/targets/azure_rm_image/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subnet/aliases", + "name": "tests/integration/targets/azure_rm_image/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", + "chksum_sha256": "fca45b39c1e6a21b8fb8e1b6c8f5954d8accf0bc6fa436361d75b014b36a8fd6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subnet/tasks", + "name": "tests/integration/targets/azure_rm_image/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subnet/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_image/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6da3c97478624fb4d675d4787caedba75a8b159228bc39d6fccdd3db6a333c78", + "chksum_sha256": "f15012224b91b0dcb340a2dfcd3d360a36bf2ed291b88a4206914ac5db295466", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ipgroup", + "name": "tests/integration/targets/azure_rm_multiplemanageddisks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ipgroup/meta", + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ipgroup/meta/main.yml", + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ipgroup/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", - "format": 1 - }, - { - "name": "tests/integration/targets/azure_rm_ipgroup/tasks", + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/templates", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ipgroup/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/templates/disk_config.j2", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b2d66c35aafd2720cb487010156156302c28f3cd0e20fcfbed1a98d2ed42601f", + "chksum_sha256": "d52e27205862487e08375c08ac7c8aa27c059db63c3fb83ebb8dd8eb0e7e11f6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adserviceprincipal", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/aliases", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ea124e6a615561c87b4dd84d829b1eb1d2bd1658d1caf6211019eeda3ffc8136", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adserviceprincipal/meta", + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/defaults", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adserviceprincipal/meta/main.yml", + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/defaults/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "e74506a8cfbf91887befefae0b179455f0071b5d904b30c00b67897373123b23", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adserviceprincipal/aliases", + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/tasks/test_shared.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "528893af1cac01f38ab277aec0138b83c74b2576464d96eb7f3da330784edaff", + "chksum_sha256": "347f0eb7c19d4e9cb7070d4eff76a456f649df4792a590d75b0258643d1c4282", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adserviceprincipal/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/tasks/test_async.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c7047ff5651f3faf6ac16b87e5434fd16dae5a620b45ed55723a208b27b9d4bc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adserviceprincipal/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_multiplemanageddisks/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4a0a40666b1bd4ba719d5da58b623587b330007a776cac80dcd1d55df48a34ad", + "chksum_sha256": "8e23e36b5f9691d484992b8472b963aa9265f9e12c2b5eace4da7b532d66c3db", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatelinkservice", + "name": "tests/integration/targets/azure_rm_manageddisk", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatelinkservice/meta", + "name": "tests/integration/targets/azure_rm_manageddisk/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatelinkservice/meta/main.yml", + "name": "tests/integration/targets/azure_rm_manageddisk/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatelinkservice/aliases", + "name": "tests/integration/targets/azure_rm_manageddisk/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", + "chksum_sha256": "b79d487ac5f66f90cfba1e03eb40daf31086e77447861b1cf4aeceee77d9745b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatelinkservice/tasks", + "name": "tests/integration/targets/azure_rm_manageddisk/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatelinkservice/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_manageddisk/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "26d7dc158898d9dbc017b66108ef335ff0b4a5ba01d2566cecbec6ad767763be", + "chksum_sha256": "c8decdddddd8660e19da01320399ff9e5216c7733d9c755a9f812f81068f7ca5", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_workspace", + "name": "tests/integration/targets/azure_rm_hostgroup", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_workspace/meta", + "name": "tests/integration/targets/azure_rm_hostgroup/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_workspace/meta/main.yml", + "name": "tests/integration/targets/azure_rm_hostgroup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_workspace/aliases", + "name": "tests/integration/targets/azure_rm_hostgroup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "08cf46c06f61ba50ecd182f45dfcf2ad7529f1df439d0ca713a8ceba58e14c99", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_workspace/tasks", + "name": "tests/integration/targets/azure_rm_hostgroup/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_workspace/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_hostgroup/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7ce589f76321d7c707ac86920720af5574f0d3e3685ef6c9aec9987393a09172", + "chksum_sha256": "a11e09783bbddbc59c9ddb098a44d5e17aaac05fec0334ef225dd2d301651e17", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlmanagedinstance", + "name": "tests/integration/targets/azure_rm_azurefirewall", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/meta", + "name": "tests/integration/targets/azure_rm_azurefirewall/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/meta/main.yml", + "name": "tests/integration/targets/azure_rm_azurefirewall/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/aliases", + "name": "tests/integration/targets/azure_rm_azurefirewall/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d19280a8d5d5c2523536ea5aed2c5a14d1b19cc49f3f21974ca3e9a9921bb7cd", + "chksum_sha256": "c00350cca0b02532fa9ae31b5fdf0d5b963615b521197b71ac4cc024aac9d037", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/tasks", + "name": "tests/integration/targets/azure_rm_azurefirewall/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_sqlmanagedinstance/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_azurefirewall/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "561193b252168d2eca301ab2c0f673e1a99acc2c807b9f9e8679f1e3b7058d5e", + "chksum_sha256": "99e09441ca9bb38a0844a3421ebdd6d6e496690d6aa853f111ec79d73108bef1", "format": 1 }, { - "name": "tests/integration/targets/inventory_azure", + "name": "tests/integration/targets/azure_rm_firewallpolicy", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/runme.sh", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "203fe16581a305486f7d5a2feafad324ed5515a96c26b4f4d84ab34a1cdcb6a3", - "format": 1 - }, - { - "name": "tests/integration/targets/inventory_azure/playbooks", + "name": "tests/integration/targets/azure_rm_firewallpolicy/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/playbooks/create_inventory_config.yml", + "name": "tests/integration/targets/azure_rm_firewallpolicy/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "96709396441733bc7e0001d045f1f825170489df8eae9cfdb677722f70e034be", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/playbooks/empty_inventory_config.yml", + "name": "tests/integration/targets/azure_rm_firewallpolicy/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "86545d143dd65f74a63218943018bfad054837e6c813fd396442957c89e87a62", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/playbooks/teardown.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "1f44c8ef223d0219855c453cd859b44b7cd4b2fa10fb1f8cacac75e020975fc8", + "name": "tests/integration/targets/azure_rm_firewallpolicy/tasks", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/playbooks/setup.yml", + "name": "tests/integration/targets/azure_rm_firewallpolicy/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e95740d1317dda6c7a610a482d33b29e2035293ff74e10a2bcc0f2997ba85430", + "chksum_sha256": "83fbfafaa9f1fc5fddcfa245b6911f0e659bbe7ec05431f59ed455b2b7b0298c", "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/playbooks/vars.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "23fff20fb969471888915a24760b7a90723a30e3e0e6b7c7745864470c898027", + "name": "tests/integration/targets/azure_rm_ipgroup", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/playbooks/test_inventory.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "40807db8218dfb3bc6b2f926c7c0ee573ddd6f6ac5b7eb3aa4cd8d013195639b", + "name": "tests/integration/targets/azure_rm_ipgroup/meta", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/test.azure_rm.yml", + "name": "tests/integration/targets/azure_rm_ipgroup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/aliases", + "name": "tests/integration/targets/azure_rm_ipgroup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e2e2f39006f1e6b83660c469a9c29e1dfb17b99cca9caa124626e14cd0658a0b", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/templates", + "name": "tests/integration/targets/azure_rm_ipgroup/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/inventory_azure/templates/basic.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "3f99d3d1c0b4f896b1f43477667fc744c2cd2d38471c5bbc9287773b57682628", - "format": 1 - }, - { - "name": "tests/integration/targets/inventory_azure/templates/basic2.yml", + "name": "tests/integration/targets/azure_rm_ipgroup/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "758f6dfaa158a3601eb9cd986357f1a40a04071ad62f3ba613002ffde00d6018", + "chksum_sha256": "b2d66c35aafd2720cb487010156156302c28f3cd0e20fcfbed1a98d2ed42601f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vmbackuppolicy", + "name": "tests/integration/targets/azure_rm_cdnprofile", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vmbackuppolicy/meta", + "name": "tests/integration/targets/azure_rm_cdnprofile/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vmbackuppolicy/meta/main.yml", + "name": "tests/integration/targets/azure_rm_cdnprofile/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vmbackuppolicy/aliases", + "name": "tests/integration/targets/azure_rm_cdnprofile/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "923b442d786cff06e0b7a3ea4232f7bfe10835e93fb73b8df6ee997380099420", + "chksum_sha256": "d922663ea733e96e4da9178ebcd4baa17435a011302f3d609f7391e651d119f9", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vmbackuppolicy/tasks", + "name": "tests/integration/targets/azure_rm_cdnprofile/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vmbackuppolicy/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_cdnprofile/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e990393d47f344ab98b507415273d6ec89117b52b4feba04783ab07d792e7243", + "chksum_sha256": "b9116be95e99a7a4650f95f59f2832c4c71c3ef74ed2b6362afea6eb5c57438c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_firewallpolicy", + "name": "tests/integration/targets/azure_rm_publicipprefix", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_firewallpolicy/meta", + "name": "tests/integration/targets/azure_rm_publicipprefix/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_firewallpolicy/meta/main.yml", + "name": "tests/integration/targets/azure_rm_publicipprefix/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_firewallpolicy/aliases", + "name": "tests/integration/targets/azure_rm_publicipprefix/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_firewallpolicy/tasks", + "name": "tests/integration/targets/azure_rm_publicipprefix/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_firewallpolicy/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_publicipprefix/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "83fbfafaa9f1fc5fddcfa245b6911f0e659bbe7ec05431f59ed455b2b7b0298c", + "chksum_sha256": "edf0f4922b32fc3156d9efabdd927eecb0dc8fbc826a0380e63b024b4e02c2fb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resource", + "name": "tests/integration/targets/azure_rm_gallery", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resource/meta", + "name": "tests/integration/targets/azure_rm_gallery/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resource/meta/main.yml", + "name": "tests/integration/targets/azure_rm_gallery/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resource/aliases", + "name": "tests/integration/targets/azure_rm_gallery/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b9685232ad3eab40ee59426a3dd04a8f71719dbfa1d6becb498bb416c8d1ff1c", + "chksum_sha256": "e676d2331077a7a453c2694fef48b0b56195d00e5a1009e3f668a7e174abd16b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resource/tasks", + "name": "tests/integration/targets/azure_rm_gallery/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resource/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_gallery/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e51cbf401d0da7fb038fade492b102a3493b57c0c0e4f9ca927d726db890c4df", + "chksum_sha256": "7d4ccb5c3257f92a672129322d603c601bcdde23ed2828b0a4e18a610545f17e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adpassword", + "name": "tests/integration/targets/azure_rm_registrationdefinition", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adpassword/meta", + "name": "tests/integration/targets/azure_rm_registrationdefinition/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adpassword/meta/main.yml", + "name": "tests/integration/targets/azure_rm_registrationdefinition/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adpassword/aliases", + "name": "tests/integration/targets/azure_rm_registrationdefinition/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0e90b0bd13c40122b87176faa412a83730dcc85c0060dffa0d7b0450d559ed40", + "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adpassword/tasks", + "name": "tests/integration/targets/azure_rm_registrationdefinition/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adpassword/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_registrationdefinition/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "448a3e37f44ca7e199c6184fedaf40e24a648ed1b1b2763b40d5c34e2763adfc", + "chksum_sha256": "b1eafe0d8ad74c931f977ad6bf378546181d7c65405504f2a68d515d453f465d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_diskencryptionset", + "name": "tests/integration/targets/azure_rm_dnsrecordset", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_diskencryptionset/meta", + "name": "tests/integration/targets/azure_rm_dnsrecordset/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_diskencryptionset/meta/main.yml", + "name": "tests/integration/targets/azure_rm_dnsrecordset/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_diskencryptionset/aliases", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", - "format": 1 - }, - { - "name": "tests/integration/targets/azure_rm_diskencryptionset/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "tests/integration/targets/azure_rm_diskencryptionset/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_dnsrecordset/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7a0a7e26e52f22c56e37dcc3154036297160820fe9bfdc27f6b5fb5811e84e9b", + "chksum_sha256": "36614727374728e26b5686e9fac66641e5b9c268b6945f2dcd1b4a9c4d2232c3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_diskencryptionset/lookup_plugins", + "name": "tests/integration/targets/azure_rm_dnsrecordset/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_diskencryptionset/lookup_plugins/azure_service_principal_attribute.py", + "name": "tests/integration/targets/azure_rm_dnsrecordset/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ecf5403290d75ebf93dd07c1a0d1ec251482cde7952d5fc4c1f51ecde936e804", + "chksum_sha256": "9d766be151f93042b7018bd39ac79b987e66389613ce426a70d5683952b5a841", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mariadbserver", + "name": "tests/integration/targets/azure_rm_privatednsrecordset", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mariadbserver/meta", + "name": "tests/integration/targets/azure_rm_privatednsrecordset/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mariadbserver/meta/main.yml", + "name": "tests/integration/targets/azure_rm_privatednsrecordset/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mariadbserver/aliases", + "name": "tests/integration/targets/azure_rm_privatednsrecordset/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0f1123b3696957f55774d4316a4461182998975a0db1f960ef289b20b5e926c7", + "chksum_sha256": "36614727374728e26b5686e9fac66641e5b9c268b6945f2dcd1b4a9c4d2232c3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mariadbserver/tasks", + "name": "tests/integration/targets/azure_rm_privatednsrecordset/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mariadbserver/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_privatednsrecordset/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b829d34d571be3c848284902c00755a940e2a629115fbbd3a78af1ce018a0ede", + "chksum_sha256": "1fc82f73aab3fbd25c62ca6e740a796a286df28c3de2cc6d084619cdb7fd12eb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_batchaccount", + "name": "tests/integration/targets/azure_rm_automationrunbook", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_batchaccount/meta", + "name": "tests/integration/targets/azure_rm_automationrunbook/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_batchaccount/meta/main.yml", + "name": "tests/integration/targets/azure_rm_automationrunbook/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_batchaccount/aliases", + "name": "tests/integration/targets/azure_rm_automationrunbook/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "049e0b8480c14a44ea8525b83848582417405cd5352a0afc5fc9bc3f1c0f3941", + "chksum_sha256": "522c2e1148926193596b31fa7cf086b9f57e17c7028abc638a2b6f5bb9269850", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_batchaccount/tasks", + "name": "tests/integration/targets/azure_rm_automationrunbook/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_batchaccount/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_automationrunbook/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f37479ad82f6ad6db65b64e25816f268071345bbfcd8f168ce2af930d0f99375", + "chksum_sha256": "a1368da2abfb774ea5e3fd1a9238e9fbadbbc6fb1a93c00685bdc1d966e401b4", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_autoscale", + "name": "tests/integration/targets/azure_rm_aduser", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_autoscale/meta", + "name": "tests/integration/targets/azure_rm_aduser/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_autoscale/meta/main.yml", + "name": "tests/integration/targets/azure_rm_aduser/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_autoscale/aliases", + "name": "tests/integration/targets/azure_rm_aduser/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2019d6f29a1dbe1242200ff0a0485722bc57431db8265a741c5e501cd5a920dd", + "chksum_sha256": "1658975f0508387cde4cda499d7eb9524e31bc2f02cc49d6483d7e210d991234", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_autoscale/tasks", + "name": "tests/integration/targets/azure_rm_aduser/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_autoscale/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_aduser/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c5faa6f6e4e1a6f51493f745f616201b1ed3447db1ec85f60ae676b8ecd334a0", + "chksum_sha256": "978e84fe852bac2909bcf4d707ecd577b164e6bd25c694464403ff855562b369", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineimage_info", + "name": "tests/integration/targets/azure_rm_automationaccount", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/meta", + "name": "tests/integration/targets/azure_rm_automationaccount/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/meta/main.yml", + "name": "tests/integration/targets/azure_rm_automationaccount/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/aliases", + "name": "tests/integration/targets/azure_rm_automationaccount/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8eb6da86566844e8278692f99177c27f5e17dfc808484e9168d842ce4ea822b2", + "chksum_sha256": "87c7ae7077faea9533bb827344f49dadfecfdbc5ea179058d72f7bad3ae81388", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/tasks", + "name": "tests/integration/targets/azure_rm_automationaccount/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachineimage_info/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_automationaccount/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c1027dcaf3ce2f749a07c7b78ee56ff713901f0fa792e08ebfc2c31671426a1c", + "chksum_sha256": "c99286c45665b96d5deea95731688470a9a02c11d22f868cb0ba7a56b71c63c5", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_rediscache", + "name": "tests/integration/targets/azure_rm_virtualhub", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_rediscache/meta", + "name": "tests/integration/targets/azure_rm_virtualhub/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_rediscache/meta/main.yml", + "name": "tests/integration/targets/azure_rm_virtualhub/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_rediscache/aliases", + "name": "tests/integration/targets/azure_rm_virtualhub/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5ba0bf8a7bf29813d54b53fd7c3e65698ee5f802eb2ccf76c1707680acc07f17", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_rediscache/tasks", + "name": "tests/integration/targets/azure_rm_virtualhub/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_rediscache/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_virtualhub/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "60978e58b15da724fb1f16447071e7b33add290150dfbdd4173900c4edda9a91", + "chksum_sha256": "8810084bf5132a43f31c425b77e96134af6d5855dcb4d4ab94ed2b691d555614", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appserviceplan", + "name": "tests/integration/targets/azure_rm_batchaccount", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appserviceplan/meta", + "name": "tests/integration/targets/azure_rm_batchaccount/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appserviceplan/meta/main.yml", + "name": "tests/integration/targets/azure_rm_batchaccount/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appserviceplan/aliases", + "name": "tests/integration/targets/azure_rm_batchaccount/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3d8b505b037b869206fe23e768d9d42e48dc8db7c83ac3023ec1be689261f907", + "chksum_sha256": "049e0b8480c14a44ea8525b83848582417405cd5352a0afc5fc9bc3f1c0f3941", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appserviceplan/tasks", + "name": "tests/integration/targets/azure_rm_batchaccount/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_appserviceplan/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_batchaccount/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f3fd1981d472300a8b2044ffbd73e928a089c2d81b3c09d7d5dff19c5d6cd544", + "chksum_sha256": "f37479ad82f6ad6db65b64e25816f268071345bbfcd8f168ce2af930d0f99375", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkgateway", + "name": "tests/integration/targets/azure_rm_keyvaultkey", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/meta", + "name": "tests/integration/targets/azure_rm_keyvaultkey/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/meta/main.yml", + "name": "tests/integration/targets/azure_rm_keyvaultkey/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/aliases", + "name": "tests/integration/targets/azure_rm_keyvaultkey/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4f59a6f1fc64a79191d0110c2f203adee747fd1bb69ad631a279efa7d370eaec", + "chksum_sha256": "36614727374728e26b5686e9fac66641e5b9c268b6945f2dcd1b4a9c4d2232c3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/tasks", + "name": "tests/integration/targets/azure_rm_keyvaultkey/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetworkgateway/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_keyvaultkey/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "271094dd7a4e013c0da515000e4e6257bb716cf030c89dbe37af7ca74902841d", + "chksum_sha256": "06c0a1c5aa8570a5ada69eae73aecfaee636bcb8f958c7dfd170c39d69c4f69d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappaccessrestriction", + "name": "tests/integration/targets/azure_rm_expressroute", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappaccessrestriction/meta", + "name": "tests/integration/targets/azure_rm_expressroute/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappaccessrestriction/meta/main.yml", + "name": "tests/integration/targets/azure_rm_expressroute/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappaccessrestriction/aliases", + "name": "tests/integration/targets/azure_rm_expressroute/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappaccessrestriction/tasks", + "name": "tests/integration/targets/azure_rm_expressroute/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappaccessrestriction/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_expressroute/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "23178ef47e9dbb43a51984becf44d72972a399952958fd2a76d71d6338864252", + "chksum_sha256": "0fee3fb92d49fcebdc6564a4becd35f638cfa294e5d893fc5adf2fff21ac072b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ddosprotectionplan", + "name": "tests/integration/targets/azure_rm_datalakestore", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ddosprotectionplan/meta", + "name": "tests/integration/targets/azure_rm_datalakestore/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ddosprotectionplan/meta/main.yml", + "name": "tests/integration/targets/azure_rm_datalakestore/meta/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a66dc9e034ad04e167bd52df4f75f2bea4499b25349fc42b3c8de9e2fe806996", + "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ddosprotectionplan/aliases", + "name": "tests/integration/targets/azure_rm_datalakestore/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1be076424fbf717d678e202250426e9b368688f8d3029f0c5dc262b97df819af", + "chksum_sha256": "528893af1cac01f38ab277aec0138b83c74b2576464d96eb7f3da330784edaff", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ddosprotectionplan/tasks", + "name": "tests/integration/targets/azure_rm_datalakestore/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_ddosprotectionplan/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_datalakestore/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cac8f7d2a8403213ad252934698c6c5eef6edc0ccd0eb6c5794990e6c30f05b0", + "chksum_sha256": "0731e52280287102127653617210703eeb3bd7abf3125367f33df7fd8d0be818", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_recoveryservicesvault", + "name": "tests/integration/targets/azure_rm_resourcegroup", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_recoveryservicesvault/meta", + "name": "tests/integration/targets/azure_rm_resourcegroup/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_recoveryservicesvault/meta/main.yml", + "name": "tests/integration/targets/azure_rm_resourcegroup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_recoveryservicesvault/aliases", + "name": "tests/integration/targets/azure_rm_resourcegroup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "923b442d786cff06e0b7a3ea4232f7bfe10835e93fb73b8df6ee997380099420", + "chksum_sha256": "cd30933c00554775a36ee6421935b7d8baf776db7cb35d5a103be9e18b7d2486", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_recoveryservicesvault/tasks", + "name": "tests/integration/targets/azure_rm_resourcegroup/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_recoveryservicesvault/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_resourcegroup/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6e841ad32da809ed4a9782a8ce178f2c8399d98a56be2406142e898afffb65c0", + "chksum_sha256": "ccf92a54443b6b7b1df4139247acd0d9496fb6266d6a99defb4035fb76cb61a3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpoint", + "name": "tests/integration/targets/azure_rm_networkinterface", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpoint/meta", + "name": "tests/integration/targets/azure_rm_networkinterface/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpoint/meta/main.yml", + "name": "tests/integration/targets/azure_rm_networkinterface/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpoint/aliases", + "name": "tests/integration/targets/azure_rm_networkinterface/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "11c35de489a3da87eb40a2ce00a80a9992fc89c3b3fdee710301ba9faacd332d", + "chksum_sha256": "79cafc6b10612f907e2e4a97bac50c9948ac0a0dd5030875a9465204a6323b48", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpoint/tasks", + "name": "tests/integration/targets/azure_rm_networkinterface/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpoint/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_networkinterface/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f5c8cc29641d123e237b894acc5d13e306e61d6cc553d15561730a42e63e55fc", + "chksum_sha256": "cd2b9fd7ff5b256d26839ba3646b9347fa95f8fd6b1104e7f2835e1d7b7b2624", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backuppolicy", + "name": "tests/integration/targets/azure_rm_adapplication", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backuppolicy/meta", + "name": "tests/integration/targets/azure_rm_adapplication/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backuppolicy/meta/main.yml", + "name": "tests/integration/targets/azure_rm_adapplication/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backuppolicy/aliases", + "name": "tests/integration/targets/azure_rm_adapplication/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", + "chksum_sha256": "0e90b0bd13c40122b87176faa412a83730dcc85c0060dffa0d7b0450d559ed40", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backuppolicy/tasks", + "name": "tests/integration/targets/azure_rm_adapplication/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backuppolicy/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_adapplication/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "26b1ed48d843898e1dc63a09a119c74ee83613ed2f0066e2971f3056eda0ee88", + "chksum_sha256": "e7b04ba312d08b8fdee715292776842a8533aed97ad6aae4c25ebcba04c8ccf2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagement", + "name": "tests/integration/targets/azure_rm_workspace", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagement/meta", + "name": "tests/integration/targets/azure_rm_workspace/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagement/meta/main.yml", + "name": "tests/integration/targets/azure_rm_workspace/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagement/aliases", + "name": "tests/integration/targets/azure_rm_workspace/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "592e63285615e1fe4768ff5027ae6a96e4dea5c875e1127e14c393cfacbc44fb", + "chksum_sha256": "08cf46c06f61ba50ecd182f45dfcf2ad7529f1df439d0ca713a8ceba58e14c99", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagement/tasks", + "name": "tests/integration/targets/azure_rm_workspace/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagement/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_workspace/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7be6584e05920691ae83bc434ef61feb54cf098cb187c6457e10234840ee6ff9", + "chksum_sha256": "7ce589f76321d7c707ac86920720af5574f0d3e3685ef6c9aec9987393a09172", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cognitivesearch", + "name": "tests/integration/targets/azure_rm_keyvaultsecret", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cognitivesearch/meta", + "name": "tests/integration/targets/azure_rm_keyvaultsecret/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cognitivesearch/meta/main.yml", + "name": "tests/integration/targets/azure_rm_keyvaultsecret/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cognitivesearch/aliases", + "name": "tests/integration/targets/azure_rm_keyvaultsecret/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", + "chksum_sha256": "c7bb4c8aa02376e55002499e1a01763a649ddf80c253e1da4556ab7719ed05ac", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cognitivesearch/tasks", + "name": "tests/integration/targets/azure_rm_keyvaultsecret/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cognitivesearch/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_keyvaultsecret/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e3712847b582b6a3a3f461055963ce51034e160b1e174d06b8b8f6eeecd4bc19", + "chksum_sha256": "e9a7c76b76aa6e2ec7471c617c9fca886aecd9f28eafb9442023426818771d7b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinesize_info", + "name": "tests/integration/targets/azure_rm_loganalyticsworkspace", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/meta", + "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/meta/main.yml", + "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/aliases", + "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", + "chksum_sha256": "f6ab21fb1deaf7061dd270b8ca0bf7c6e585eac172153559349e997150abbcaf", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/tasks", + "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachinesize_info/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6684f96227d75c363a588e1be85cc7ce53025d7e13844638d100781003901db6", + "chksum_sha256": "529ae2dab2d63d3af2eab9ff5fe9b466a9c2bf3bf600d0a5221126ddec9be288", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagementservice", + "name": "tests/integration/targets/azure_rm_datafactory", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagementservice/meta", + "name": "tests/integration/targets/azure_rm_datafactory/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagementservice/meta/main.yml", + "name": "tests/integration/targets/azure_rm_datafactory/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagementservice/aliases", + "name": "tests/integration/targets/azure_rm_datafactory/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "528893af1cac01f38ab277aec0138b83c74b2576464d96eb7f3da330784edaff", + "chksum_sha256": "a74040b53394bd68b1885c350f1f62603740e721ca38e01609660895693a3858", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagementservice/tasks", + "name": "tests/integration/targets/azure_rm_datafactory/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_apimanagementservice/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_datafactory/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "db17a45674ec599ab8fb1890903d3bc49b3ded000197dd55cc82c3017a962565", + "chksum_sha256": "eedba69010cd9dad1b57c7e0f7f18eacb0feb43359922cb53c3ba98479e8dfcc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultsecret", + "name": "tests/integration/targets/azure_rm_storageblob", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultsecret/meta", + "name": "tests/integration/targets/azure_rm_storageblob/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultsecret/meta/main.yml", + "name": "tests/integration/targets/azure_rm_storageblob/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultsecret/aliases", + "name": "tests/integration/targets/azure_rm_storageblob/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c7bb4c8aa02376e55002499e1a01763a649ddf80c253e1da4556ab7719ed05ac", + "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultsecret/tasks", + "name": "tests/integration/targets/azure_rm_storageblob/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultsecret/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_storageblob/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5c0ffa5a2e80c5c71996a8f4fe46816621d764b46f0f7bc23560b55e2072d5e7", + "chksum_sha256": "7175cd6cb47363104377b380cc011fa46f815bbc69b2d81cbd347786159bda9e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultsecret/lookup_plugins", + "name": "tests/integration/targets/azure_rm_storageblob/files", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvaultsecret/lookup_plugins/azure_service_principal_attribute.py", + "name": "tests/integration/targets/azure_rm_storageblob/files/Ratings.png", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ecf5403290d75ebf93dd07c1a0d1ec251482cde7952d5fc4c1f51ecde936e804", + "chksum_sha256": "20cdf86ae984fb64eefdc57a0e03f34c83cb8b27834b33c84768cc2b62cf9d68", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_eventhub", + "name": "tests/integration/targets/azure_rm_roleassignment", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_eventhub/meta", + "name": "tests/integration/targets/azure_rm_roleassignment/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_eventhub/meta/main.yml", + "name": "tests/integration/targets/azure_rm_roleassignment/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_eventhub/aliases", + "name": "tests/integration/targets/azure_rm_roleassignment/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1be076424fbf717d678e202250426e9b368688f8d3029f0c5dc262b97df819af", + "chksum_sha256": "51bfa0d69b7c8b7e94b28aa9c60c921ace3971f50a385673a66791c31749678a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_eventhub/tasks", + "name": "tests/integration/targets/azure_rm_roleassignment/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_eventhub/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_roleassignment/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c4ef2c774f92b1d1c61c070407cb15cec4492593f03dfc095031136a6fc315e4", + "chksum_sha256": "46a3ce70c6a099b76908d0787935c2fb80ab988391f5d91790e3157bec81a8c1", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_postgresqlserver", + "name": "tests/integration/targets/azure_rm_diskencryptionset", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_postgresqlserver/meta", + "name": "tests/integration/targets/azure_rm_diskencryptionset/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_postgresqlserver/meta/main.yml", + "name": "tests/integration/targets/azure_rm_diskencryptionset/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_postgresqlserver/aliases", + "name": "tests/integration/targets/azure_rm_diskencryptionset/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "212c2162821130244834f49afd3460bb037d426eac902fc88de51afbe6bab522", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_postgresqlserver/tasks", + "name": "tests/integration/targets/azure_rm_diskencryptionset/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_postgresqlserver/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_diskencryptionset/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "957431198f2f2412d381532922a380b37d3a2941dce8f6fbcda89284fa7d3ca5", + "chksum_sha256": "a53089acc4661e0553413e5be4b73155cbe81c5774ffc33e53470b7f0a192709", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_publicipaddress", + "name": "tests/integration/targets/azure_rm_proximityplacementgroup", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_publicipaddress/meta", + "name": "tests/integration/targets/azure_rm_proximityplacementgroup/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_publicipaddress/meta/main.yml", + "name": "tests/integration/targets/azure_rm_proximityplacementgroup/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_publicipaddress/aliases", + "name": "tests/integration/targets/azure_rm_proximityplacementgroup/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ed3159c0b56e6e42548ed58456e5304d48aea0b4e3a0999591f863ae79b225ba", + "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_publicipaddress/tasks", + "name": "tests/integration/targets/azure_rm_proximityplacementgroup/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_publicipaddress/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_proximityplacementgroup/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0240ae96de6dabce7cd47a7793fb7a263717ea1b2e28423f47ba0c75333ed8cd", + "chksum_sha256": "c5c88276931feb2e7c2b7386c1ed4885d19888d5f70cf8c76dd4088fa33fa79d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_servicebus", + "name": "tests/integration/targets/azure_rm_vpnsite", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_servicebus/meta", + "name": "tests/integration/targets/azure_rm_vpnsite/meta", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_servicebus/meta/main.yml", + "name": "tests/integration/targets/azure_rm_vpnsite/meta/main.yml", "ftype": "file", "chksum_type": "sha256", "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_servicebus/aliases", + "name": "tests/integration/targets/azure_rm_vpnsite/aliases", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "923b442d786cff06e0b7a3ea4232f7bfe10835e93fb73b8df6ee997380099420", + "chksum_sha256": "51bfa0d69b7c8b7e94b28aa9c60c921ace3971f50a385673a66791c31749678a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_servicebus/tasks", + "name": "tests/integration/targets/azure_rm_vpnsite/tasks", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_servicebus/tasks/main.yml", + "name": "tests/integration/targets/azure_rm_vpnsite/tasks/main.yml", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a0528bf0af2a590fe46bced0ca843722543d5f10626604a887a7c278e97c38d2", + "chksum_sha256": "bcfd0915de197ad7e6d01dd27e5ffe2a8f62d93303f19d5e4c09373a82dc7334", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting", + "name": "shippable.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "515333579eea59619360d72e38cc2c5c9a8b43ff59cd3ddcc12c5b0172553b4a", + "format": 1 + }, + { + "name": "README.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "addfda03504e77be9156f1d5a1dec8ec3d9f81d08498ac814e7f782adbdc0e21", + "format": 1 + }, + { + "name": "CHANGELOG.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9968490b2917b41466fcf58ff804ea27213672db0b91ac0f55ce076246a69913", + "format": 1 + }, + { + "name": "requirements-azure.txt", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5ed84a767e40fa7e5bdb9dccd739cb355185b1414a1beab6892a1bb8d3e6062d", + "format": 1 + }, + { + "name": "plugins", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/meta", + "name": "plugins/doc_fragments", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/meta/main.yml", + "name": "plugins/doc_fragments/azure_tags.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "e8c9d720dbc7605d3ee66799e8e81d0886e404c9a07b6b9b8edc844e0646de64", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/aliases", + "name": "plugins/doc_fragments/azure.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cc618d5714ddaae8f1482cf89dcf3327cf82fa378c16f6b5cf092339927261c3", + "chksum_sha256": "f2146d8b6b05f3dc1571069061663ff89f7527880e36a7f4fc4ac2e87ef0ee68", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/tasks", + "name": "plugins/doc_fragments/azure_rm.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0342c35022e2762f31a487c0434feda2cb4d74717e474c0f3ea6735266c36b6b", + "format": 1 + }, + { + "name": "plugins/module_utils", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_monitordiagnosticsetting/tasks/main.yml", + "name": "plugins/module_utils/azure_rm_common_ext.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4c185b22edc1017409894f57875fe5db2c986c6d741cbd86dc78aa01b36a9fc9", + "chksum_sha256": "ebf7c0c6f4ad7a05a04d740ca989a05cc4b22728acbd6390d9aa90931eca1647", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aksagentpool", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/module_utils/azure_rm_common.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0f2d416d8b73431c47251128c3a0b7eee12c412cc63f951ffc64caace37920ac", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aksagentpool/meta", + "name": "plugins/module_utils/azure_rm_common_rest.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a2ab0b372745c307c31073df9ff4c0d1858a996c6354fb28545ef3a529b40519", + "format": 1 + }, + { + "name": "plugins/modules", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aksagentpool/meta/main.yml", + "name": "plugins/modules/azure_rm_autoscale_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "7494564289cd93cb8e34bf724deff6fd4fb7ea335233703e1aa2a930860e1d40", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aksagentpool/aliases", + "name": "plugins/modules/azure_rm_storageshare.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "783d6dbd1b9cc4b0543d6e96d15206283018e0c291764a2a4106e860d41cb210", + "chksum_sha256": "d70dd044b1bf421773c6438c7c9020906810f7e1e74523e8855133a8fae9360d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aksagentpool/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_batchaccount_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "570fba1885df5ea2f8bcfef3e8ed9b30ca958e08aebbf85ec81724df89b76afc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aksagentpool/tasks/main.yml", + "name": "plugins/modules/azure_rm_iotdevice_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4bc2ac2faed9ceba28dfb24dffff6d996da42cf6aac09cb3a57c044a17bc046b", + "chksum_sha256": "87e22ba60e4ab700ee3bfad366690b044125b0f66091c88bc346dcc88e722262", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvault", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_cdnprofile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b23febe97f2dc337605573cd3dd1921435ae0fb89e5b765611fdbd69bec29878", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvault/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_privatednsrecordset.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d2332100a1ca9ed31dbc1a41c229aabbd02015e4f516faf8cc3dbf739bc41966", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvault/meta/main.yml", + "name": "plugins/modules/azure_rm_iotdevicemodule.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "83d5ceb43eb948e8d5e766caa60e03a9978939ff7f0132ae5d71ad5622dad3bf", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvault/aliases", + "name": "plugins/modules/azure_rm_mysqlfirewallrule_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "726101a2dd7238a8ff7f94fec489e5fcfd8bb0db10ecd074fa0686b2eb9d6d24", + "chksum_sha256": "2c98b91e48ddf042f3fd0847c42b7d880fc00ed807437aa70d35ae1107ba1407", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvault/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_vmbackuppolicy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f5053078d5ae59f0b466044d135108197c119a34d79f826be509d57dc2a6e2ce", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvault/tasks/main.yml", + "name": "plugins/modules/azure_rm_privateendpointdnszonegroup.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "85d1f060912261e42affe3f43fbe52750e62bc5d2fe7d9b55f604be778052033", + "chksum_sha256": "d516440379341b68c65581c8d9da78f6a204845502e408c48875851c58229241", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvault/lookup_plugins", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_privateendpointconnection.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9ecc4f6823fed8b227500c7714851dcc9f398424d5774bf89f8dafca9afcbef3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_keyvault/lookup_plugins/azure_service_principal_attribute.py", + "name": "plugins/modules/azure_rm_adapplication_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ecf5403290d75ebf93dd07c1a0d1ec251482cde7952d5fc4c1f51ecde936e804", + "chksum_sha256": "e04053b0c584772df10dcd46845772eefb57116b655ced27ee6786fff8334f12", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_bastionhost", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_containerinstance.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b3c13189f840de2aa3047eeb145d3f1680c40a999a45b92325f70a92ff950296", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_bastionhost/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_privatednszone_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d1ed854fff931a8a0295b9a4f82235bb9ed8cf5bb947377c51931bcf94dc4c9f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_bastionhost/meta/main.yml", + "name": "plugins/modules/azure_rm_mariadbfirewallrule.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "6c028f0fdd933b4a02b6c92f20432fc3617072d8828898f628e02554d25c31e3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_bastionhost/aliases", + "name": "plugins/modules/azure_rm_subscription_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d57abe6f8fb0cbfb8ac22431c09126cd48bb4d2836a6d151faf92fb6fbecc6aa", + "chksum_sha256": "27171c677f1e2b5337edce509b64021d2bb2708d2b476137b3e4ac96df1631af", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_bastionhost/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_privateendpointconnection_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a1c9260c99294e6c9f4579310504bf656d46b2ed16d22188859945cc53563fc0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_bastionhost/tasks/main.yml", + "name": "plugins/modules/azure_rm_firewallpolicy_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b2adf15d8a7ef9e0b56dba6b3ebe750f09192d86ec56df6076088fd4edd444e3", + "chksum_sha256": "1e1cebf4f29a286751549a9a5ccf06451bfb9648151d54ca813646f1289dc8b9", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerinstance", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_automationrunbook.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c257d3afae0b00ae9b09d6d5f04373def1e678ea99cd8d5778c8425d64ea0058", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerinstance/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_keyvaultkey_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "90b03fb0478760694653e6c892acf951832ac5dc00aa4ef597507854f7d1439b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerinstance/meta/main.yml", + "name": "plugins/modules/azure_rm_webapp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "a420da6e6d479985a088e2f2c614bc462ad003d5814d81e4a6db489aef906a83", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerinstance/aliases", + "name": "plugins/modules/azure_rm_galleryimageversion_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "059ec72ab54682d34b109880aa48f5b5b702d120042153371442c7293c011f31", + "chksum_sha256": "dc2dffd74aa500eb855ecebf3abbec93da09ef7cf2805edb11a498ed33f46205", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerinstance/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_iothub.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "aee9f30afbc1989ff7cfe64101c59d842dc635e59b34411d4045c428f1109b1d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerinstance/tasks/main.yml", + "name": "plugins/modules/azure_rm_cosmosdbaccount.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d5d577eb39a4533fea27bd3240b4ffaa278f64b5f56b5c6375c0d1e73b7ba382", + "chksum_sha256": "71100c8b3ba6cf9fd59776ae0b50d9e9ba4e34036ef6a5ba3821a6cf7c907d17", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationassignment", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_roleassignment.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "981eea70440c35499110fa7a97cc7259e7cac1ed2f790ffcb1c247a51bfa6fe3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationassignment/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_akscredentials_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6635a6c530e584f50ba8d60da72e9d6e6814cd45ef73d155e9a9999bde3e70f8", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationassignment/meta/main.yml", + "name": "plugins/modules/azure_rm_sqlfirewallrule_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "71e6d450073de8c90623f4048d44bd6eabaa39c36031a9beba28171a53b302cd", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationassignment/aliases", + "name": "plugins/modules/azure_rm_adgroup.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", + "chksum_sha256": "152a3792aa58f812d46db9dc8b8ebfd3c78abf0406297d4b4c274ba23b398a1e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationassignment/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_virtualhub.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "be9396630b6c0d0cc7dae7688cd87421f4770dbba2ed92b2712761ff722ae8a5", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationassignment/tasks/main.yml", + "name": "plugins/modules/azure_rm_firewallpolicy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "86581a9afe3f4c3e4f7021f214e089c84267a3b909312cba226a9011c223bc9b", + "chksum_sha256": "58980ae98ef0f3eb07237bd685eaf312369a68a484aaebef40037697d83cdec1", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adgroup", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_apimanagementservice.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "02a98c1b1f61d2b4ff90bc1ac35710efc9590514b19f500cfae1698216cde019", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adgroup/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_publicipaddress.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e2ddc75d7edca49904c6025a1e1418c0ada1ed45fd56963a8e315cf7b2074362", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adgroup/meta/main.yml", + "name": "plugins/modules/azure_rm_functionapp_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "1e0f3de0ed340f2e1a5cb2b5b4cb8b7cc9c6c8eafe4483cdb38b58878482b589", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adgroup/aliases", + "name": "plugins/modules/azure_rm_webappaccessrestriction_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0e90b0bd13c40122b87176faa412a83730dcc85c0060dffa0d7b0450d559ed40", + "chksum_sha256": "c72ded459dbd8c58642c77aba5cfab56a86782f4e19958ded25f9754a32c1591", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adgroup/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_manageddisk.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a4047fdb47da55f8bca9f6d0db734f6a74a0de61c644ca6ad98718f3eb808fe4", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_adgroup/tasks/main.yml", + "name": "plugins/modules/azure_rm_aks_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f4adb4bc8784bbb857a39fbe58f45a1a47853538f3207e987b8bd64b1704238b", + "chksum_sha256": "3498eef981aba56a6540bf90b9a34c194dceb70503d43483c8ba64f367b2ba83", "format": 1 }, { - "name": "tests/integration/targets/setup_azure", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_dnszone_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "15da62156897e9dc73a74650198e57b4d6dce5bb761b1e0b0c86d19be31f1cce", "format": 1 }, { - "name": "tests/integration/targets/setup_azure/aliases", + "name": "plugins/modules/azure_rm_ddosprotectionplan.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "chksum_sha256": "b5eb8ad5fe5b146e7b79f083f2f9747b1bc64432bc55660ac682e97e8235f023", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_loadbalancer_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b6b508842cc40fd4310a90e2bbad7733a50b7c43e29dc73dbccb304940b0f53c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aks/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_adserviceprincipal.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0eae69b33ff82053a9f3d85499ba935b13c84944f5ed3b355e606744b4de2ff2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aks/meta/main.yml", + "name": "plugins/modules/azure_rm_ipgroup.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "2aaffe067e785adc4ccb4a78a2a2d665ee6e2bd5a28b79f75e2be4695a1ce115", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aks/aliases", + "name": "plugins/modules/azure_rm_aduser_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "783d6dbd1b9cc4b0543d6e96d15206283018e0c291764a2a4106e860d41cb210", + "chksum_sha256": "59f317a97611776b87dd9d822f4234368027d5de8b98730851ba644ee9259031", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aks/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_keyvaultkey.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "40084b9ca5f23d33a04cab04ec5719eae2f6c76cca3ea9d6741e3fa167b67577", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aks/tasks/main.yml", + "name": "plugins/modules/azure_rm_mysqlserver.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "683619ec3541848983b2f513eae4d885c97d3040ac188d252aec7304c3440c0b", + "chksum_sha256": "7f7cb3ce5875e72550cd314cc3df490cbbce0292265c927038897d026b573514", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_aks/tasks/minimal-cluster.yml", + "name": "plugins/modules/azure_rm_sqlelasticpool.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2b2be2027bb762b22ccf731a32baf3fa8b2675369c08b76c1499b3ea10902add", + "chksum_sha256": "a127cd3108b9eff43c793296f6239ee10df0810222dae4c44b380e45c01e36eb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistrytag", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_backuppolicy_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f16cb70c198028b5273e9d89ad554ed6a8e40217284a1fafb9658121c415b4b0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistrytag/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_bastionhost.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ade78abbea1c467a8bf4787d227a0a96979482b15d05e3dea2ede57f91ff6f7c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistrytag/meta/main.yml", + "name": "plugins/modules/azure_rm_mysqlfirewallrule.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "8d012c884bd3e4f7880fee699b3b6c8210a1cc00c98a2166c68c8b7e6a052bc2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistrytag/aliases", + "name": "plugins/modules/azure_rm_trafficmanager.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", + "chksum_sha256": "9aba8d8ba13076c53f797b5c999af3dbc951849450ca138ce6572804eed67a22", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistrytag/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_sqlmanagedinstance_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6c643b009b8c783f2aada97bee8f08d75012ae7b57270fdc5542b39defe37cbf", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistrytag/tasks/main.yml", + "name": "plugins/modules/azure_rm_diskencryptionset.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c3f1c91c39a8986e9aaaaf4e0f2bd84796f20ede51d7868e74a37a7839d1759d", + "chksum_sha256": "d4f85b7a7c7da95b7fbd3a084a15af87fd037134c527056a14f48ae1e58b9a9f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_recoveryservicesvault_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0049b577406a917161abd36167c9008e99975dda492874c3ed46c20875408c12", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_mysqlconfiguration.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fff34c89e959affced009f321ef5cd6b6ad9955e711d69306f339ca4c15392e0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/meta/main.yml", + "name": "plugins/modules/azure_rm_rediscachefirewallrule.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "57d39a29b5d1e1241c24251018816439bb311f70311da75555af64edad9adbee", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/aliases", + "name": "plugins/modules/azure_rm_routetable_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "11c35de489a3da87eb40a2ce00a80a9992fc89c3b3fdee710301ba9faacd332d", + "chksum_sha256": "1e849400c3b71a0bb6652ab1d40e919288b3dccb94314230273850f31259de8b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_virtualnetwork_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "39cbe4ccb66acb4dd36b893c9cb000846535c0726b8960e541a47f576fa2ed6f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privateendpointdnszonegroup/tasks/main.yml", + "name": "plugins/modules/azure_rm_lock.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "408a60ac3331b6d89792e393613ca595886d842ab4ecc6825e6dc15bb02faf86", + "chksum_sha256": "858b4a4357dd80fbefb9c62265d91f31019794c9077526f6703c95b5d7c077a3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetwork", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_networkinterface.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d6f2859a51857b23dd42dc71b71005de7a540c1b8f68178232237a4c0ac06e14", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetwork/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_postgresqlfirewallrule_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "53187b006213c221bd5391b2b45734080afcd9e63280f4181f6355b5db7258dc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetwork/meta/main.yml", + "name": "plugins/modules/azure_rm_iothubconsumergroup.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "9d6fc8dba8ecd841d908a4b1226fa0a186c270a9eb3e8a5a054692e56c621876", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetwork/aliases", + "name": "plugins/modules/azure_rm_servicebus_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", + "chksum_sha256": "1ce20b5639787edf674d44a5896e7258cec1855d04bc619f49da51740dcccf82", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetwork/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_dnszone.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a9974fc3f305a83840b041b02158be7162a6c87c8fb3a3b909a2ac6255390668", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualnetwork/tasks/main.yml", + "name": "plugins/modules/azure_rm_notificationhub_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e46b1abb1ab82874622d1821b564cee555be16ced454a9723f3cff45dcb5948c", + "chksum_sha256": "07c91492398c62e54b267d583d55287c485fbe4ca5112305e0c0cb0883500e89", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cdnprofile", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_containerregistryreplication.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "94d2e1237ef94377586760a091785272818db4bddc6a54d24badee82d7697437", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cdnprofile/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_azurefirewall_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c0c5832150dbe6fc7675980c7107ca532191e9c8b1b6885456bb3c954c45aaab", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cdnprofile/meta/main.yml", + "name": "plugins/modules/azure_rm_apimanagement.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "d414f8a53136b821e89e6adabf4be8bffe9e38b49350d547f1c2e1900b48d1e2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cdnprofile/aliases", + "name": "plugins/modules/azure_rm_rediscache.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d922663ea733e96e4da9178ebcd4baa17435a011302f3d609f7391e651d119f9", + "chksum_sha256": "c5363ae787f296df9b42f82727f81cfca5429ec971b67eac4132be52f6562400", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cdnprofile/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_monitordiagnosticsetting_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3fa25b176b8c073c9435901c2c8455577e64a998c71b5c6a472ae1044f48bed9", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_cdnprofile/tasks/main.yml", + "name": "plugins/modules/azure_rm_virtualnetworkgateway.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b292a101e30c2cf1ddb3541d9d1827483b29baea9a909cdfa57dfb9a24827741", + "chksum_sha256": "59e1d99084af0027d2c970a9e6ab6088546f4768d151a045b70615cff47b05c3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subscription", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_securitygroup_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "961d9d5ad4d46ff1acf101c19ebd88813d5251f89ec7e1f4ea809827cc3b5392", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subscription/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_autoscale.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d70f6911bb558f59f68dcc61f42155c1f108526ed47e7ad3bd8f653ade1a4f8f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subscription/meta/main.yml", + "name": "plugins/modules/azure_rm_proximityplacementgroup.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "c39137e4926c1749a04adc516a027a08e7cf2ebe2b21e7a95675fd0a546777b9", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subscription/aliases", + "name": "plugins/modules/azure_rm_route_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", + "chksum_sha256": "ec951f25bdc8b4944f43e054e44fc1887fbdb8cfaf892f5ce57174cf251b442e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subscription/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_subnet.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "356179dd240df193753fec302eae97fbf814fc4b8cd61868564449f9f8bd302b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_subscription/tasks/main.yml", + "name": "plugins/modules/azure_rm_snapshot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cb18a11b4b6b14912f9fcc0131c232c9d3525d14a8d43ee4b2606cc2d3f7249c", + "chksum_sha256": "375ef0d94cddabb5e18bcaaa773b34cfbf7bc3885745ee4ed1e6f291974db559", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_notificationhub", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_automationrunbook_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "bf2d4439d7ef7f6b0f0ec04b345e5919fef980d15b6fb3fda111c2df53c18d16", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_notificationhub/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_resourcegroup_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3336b070c7a607adde16279cdeaefe260b75c683a0ab0028b4ae6f262ebd32d8", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_notificationhub/meta/main.yml", + "name": "plugins/modules/azure_rm_natgateway.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a66dc9e034ad04e167bd52df4f75f2bea4499b25349fc42b3c8de9e2fe806996", + "chksum_sha256": "fe420872335d019070072b7541d79579eba9887f0d80e96d195ed1aaa051aea5", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_notificationhub/aliases", + "name": "plugins/modules/azure_rm_mariadbdatabase_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1be076424fbf717d678e202250426e9b368688f8d3029f0c5dc262b97df819af", + "chksum_sha256": "abe1fd7778f01c877a7c8d74170c74a26e39de0d5295b3e856adcc39fc7367e8", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_notificationhub/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_cognitivesearch.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8665ce3ff083d18608c7ed9b5fb778d6248e9cfcc096b464535d041457d9af00", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_notificationhub/tasks/main.yml", + "name": "plugins/modules/azure_rm_manageddisk_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7f519a0026da2e72a6633b7e82a4c2ae581c50b918a5291b3b4737360211276b", + "chksum_sha256": "3b7b7131b77965c67a34ae4c9ddb9def5c3d30a5a76498c51580486063693f71", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationaccount", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_virtualhub_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3a9de2d79f400506887f8b86b4a8bbfffb0e0558eae4ce954d8410beff977af4", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationaccount/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_appserviceplan.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4230691a8fb4f96611ff509e19f598304daf58104bd7c4e01b0d3e90311a2a93", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationaccount/meta/main.yml", + "name": "plugins/modules/azure_rm_virtualmachine.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "b002dccc80c26c8960dc842680bbcce59ec55561a5678d73c5ab1eb248183ce0", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationaccount/aliases", + "name": "plugins/modules/azure_rm_backupazurevm.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "87c7ae7077faea9533bb827344f49dadfecfdbc5ea179058d72f7bad3ae81388", + "chksum_sha256": "697611d8016ee00fdf81ee52c5d2174b670b3aa4a602498220cb4f1ffb455f9b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationaccount/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_virtualmachineextension_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f845763404b68b32efe0187e0224cf30b7c71366531b4de508089df01f4849a3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_automationaccount/tasks/main.yml", + "name": "plugins/modules/azure_rm_resourcegroup.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c99286c45665b96d5deea95731688470a9a02c11d22f868cb0ba7a56b71c63c5", + "chksum_sha256": "20900d4b10ee5f7032fc409be2eaafc00521f8799c56559d8ac88fce00e4b2eb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_account_info", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_postgresqlflexibledatabase.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "60fe7ebe09af6adc823fcaf3015053ce6e958e114e20b1ebdfd7aee3564ea8ee", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_account_info/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_privateendpoint_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b34126d4fac558a5077869099cf1327fbecfeab36e6e34b30c4fe809d59b92de", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_account_info/meta/main.yml", + "name": "plugins/modules/azure_rm_azurefirewall.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "b4ca4d0d3c53b3b1cae912d609f7c50ad64e60ef826de3ea07ba2976a625f8dd", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_account_info/aliases", + "name": "plugins/modules/azure_rm_iotdevice.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a58bdac3b7068e244f2cf71f0a1a0bf136bc8785d2a8947fecbafdd97313adb7", + "chksum_sha256": "9e408c7a58814207bff9d92faf6725b49be428ddb10feffdcd311617c0ae2b8f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_account_info/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_applicationsecuritygroup_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "805be7606a6145a9b4c942f63a9aa46ffc10366b8e3bf2af0c64b8009d0ac9eb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_account_info/tasks/main.yml", + "name": "plugins/modules/azure_rm_dnsrecordset_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4a18344a391206dc34d9e73134c7e2a2815ae3cdc36cf9b6791ac19e1bc07d6a", + "chksum_sha256": "ce13d83217e276a01bc5763cdfbd131090b35c64607738dc052b7ef9d25a3068", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_notificationhub.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "025163a4ad192ec7b4ec14e8faf49b01e29a8a8f38cd8231aaddec9726f460bb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/runme.sh", + "name": "plugins/modules/azure_rm_cdnprofile_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8d9a70f8c75d9a856cd529ae8ccb6e589c0db9494da4bb08cead6963e98d9dd5", + "chksum_sha256": "f860571746ea4763e349ddef498e678e62fbe5fb0af156aecd458c3b90801e96", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/main.yml", + "name": "plugins/modules/azure_rm_storageblob.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "49c03342521da6b25da0d4df975ee81e10e8b1e7ebd1bdabeba797463bceddbe", + "chksum_sha256": "25c3fe01b0eabad043577ed544d29f7014af8e68a2482ddda72830ef900ae7df", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/aliases", + "name": "plugins/modules/azure_rm_sqlserver.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "deefc8fe8e3699aa1e8852f316f52c0037219050b5b5d07919fa24d06ac14ed5", + "chksum_sha256": "9b0f2f7674cdb4641de9a2b8b50cb74e91e36ce0a07e0c3a13330592574bee71", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/inventory.yml", + "name": "plugins/modules/azure_rm_mysqldatabase.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "979c1f5123e61d083ca0ddb9816bd3381e6c2f830ae2a96648f2d4dd720a0f8d", + "chksum_sha256": "84c32c802f65e5ee577ec3e25aaab5d6d260376ddfd32368370b74ac08a24b6d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_containerregistryreplication_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b88adc68c275d1c2608313a8bca60f7805a473e33df0ff3b75b3ea0deb915195", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_dual_nic.yml", + "name": "plugins/modules/azure_rm_adpassword.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ee1ca82e2f43899c6dc17f2bd4710229f33c31aec6beb8ad9093e436d2df5b1f", + "chksum_sha256": "08837d90c0de64193acde245d3f3db12dac3e3fd548ee18275b7a847092c0698", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_spot.yml", + "name": "plugins/modules/azure_rm_roledefinition_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "40cfa7a636a0741e3f17deb1c7b965fbc42074f3fb7a50503dc93b9c2515a2e4", + "chksum_sha256": "0763daab445d3b0ce948955295bbe7a33f6aed80ffa01f86aa6d2b9808b9b6ae", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_public_ip.yml", + "name": "plugins/modules/azure_rm_cdnendpoint.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5dbfe466ae3aa493f04b91016c88318774d3e974304b90d882ed60c7ae8e2a93", + "chksum_sha256": "e42d48c18eb6e54441bb4ca6f973876cd88b083883e5a28bb634c1b39a049f6f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_vm_identity.yml", + "name": "plugins/modules/azure_rm_privatelinkservice_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a7b73bb1af0583758961a25336d5faa2eb76fe6e84b3b9698b1bc5e53fbe4f9c", + "chksum_sha256": "02a72af00f3442e3cb5a19ba01bffc4cb2d47f646abf1a5ae0a125e80a8313ba", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_invalid.yml", + "name": "plugins/modules/azure_rm_devtestlabartifact_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "055893c82ae8b817fbcd3287b7435ae35ba8d6825ad3cb9545048ac599f9dd56", + "chksum_sha256": "714452d937c197d48b0197b3b5ed5b576cda49ffd49092581715d95f0436a4ff", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_minimal.yml", + "name": "plugins/modules/azure_rm_virtualmachinescaleset.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6ec63fe982d7ce8d65dadd74eb7e5c3678fa88e008ddfeaa43b1d3b77e094583", + "chksum_sha256": "98357220f8f1ad4fd4ecb6ac3d542487cd2e62abf7ad4e068f83c3d6797fe4fd", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_image_specific.yml", + "name": "plugins/modules/azure_rm_gallery_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "41a71c6515836e0c1c764ae83a0c999403e1fb774a55c5ab7912bdf7f1e2fc89", + "chksum_sha256": "13939381263c0bcd756261bcd5727bd7f33123f49dc1da05e88c652b468e66d9", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/setup.yml", + "name": "plugins/modules/azure_rm_applicationsecuritygroup.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1af862edc4a550cf631bcaa7a082d23451a3e7eacd0a248e4688bcc8dc6ef604", + "chksum_sha256": "58f5338441960bf8824f1ed9eec52bd6c5c2ec9d8c6ab02e8a5872afd388ed39", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_ephemeral_os.yml", + "name": "plugins/modules/azure_rm_roleassignment_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5f3d3633f808a35e23202cc9be4436f7ee590314694016377f7d40b357e4d00d", + "chksum_sha256": "3287b7ad7063115ef66dc443b05f4ceb6bd22d46cd8fcec1350c6e9e64289b3f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_no_public_ip.yml", + "name": "plugins/modules/azure_rm_postgresqlflexibleserver.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a7f201260799a21031f75d3ecbd6cc372007c3a2c5ef7a6c9d35053129b868cd", + "chksum_sha256": "ea3b2ce15955406227c0367da00cebae6c44e18b9ef0c47720367e4fdd9397fc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_image_latest.yml", + "name": "plugins/modules/azure_rm_cosmosdbaccount_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1d3000da1ae66217ff40113749e77538bee7ebf49e1808ad36488ca33d89761f", + "chksum_sha256": "b26c589e01d813fd752e5563ca77f5ed254c4b57699e23780d1d4ba23780b09f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_deallocate.yml", + "name": "plugins/modules/azure_rm_postgresqlconfiguration.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fc53572c2732984518157aaff50942ab77426127a14f2e81faddfd45dd039e4c", + "chksum_sha256": "c5a5c9f631bc9ef1eb1d64acd039457dc38a52c84e5246589b9f42df904aa37a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_minimal_manageddisk.yml", + "name": "plugins/modules/azure_rm_virtualhubconnection_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e10179f3c286b53a8347a1cd7d3672cc80e9184589dc7ea292489279fcc67ede", + "chksum_sha256": "948b85322d1c84b4eee3709f69f2de166232472a675dd26e125c099ce13517cc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_no_nsg.yml", + "name": "plugins/modules/azure_rm_automationaccount.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "97017436c84bdbc87de46cee90cfab5edd108685b439253083f141cd5fd52a78", + "chksum_sha256": "5dd5fd70d816d33733de4bd4eb9f7569038760a5d13f9f932d7cc94b8077bbf4", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roleassignment", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_virtualmachinescalesetextension_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0c32b71b14bbb8c0609f20d2c522792ad6f6e5bd3b8477dfadae9bb34ae61cc2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roleassignment/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_datafactory_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "97332f814785d6c0aad03a37f0126454115c0f219379529fefa421bf9ea20b53", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roleassignment/meta/main.yml", + "name": "plugins/modules/azure_rm_devtestlabartifactsource.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "948df3ff5d5d5716e2fb15644bbf6fbacefbd51b422cbf99d7155c661216a700", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roleassignment/aliases", + "name": "plugins/modules/azure_rm_openshiftmanagedcluster.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "51bfa0d69b7c8b7e94b28aa9c60c921ace3971f50a385673a66791c31749678a", + "chksum_sha256": "90da0b66cfa28d2a546a44d0e21e9b28c3165db49ded31034537b4785a4d37a5", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roleassignment/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_devtestlabpolicy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fc13943e64dc93aed3f76eff9b1715d5b95c5f528dbcfdf3214e4d69d29f2acc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_roleassignment/tasks/main.yml", + "name": "plugins/modules/azure_rm_privateendpointdnszonegroup_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "77fcaa43c9c8308f544b5ffa24411dcdcd67f1957ff1c7ff2831d451eb5fb9b2", + "chksum_sha256": "70582f1fa2c40f77e166f00242bd6bff2e7c018368beaa2ac960328c341faa77", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_securitygroup", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_keyvaultsecret_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "545d2ced807066e6a1d44b20bba6e589cc022654f099ef9087865b18759bc73d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_securitygroup/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_ddosprotectionplan_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9ea0ae1f2bcab647085f83b8223d763abf123afe3996d0aeb0f304fc8d4fc7d3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_securitygroup/meta/main.yml", + "name": "plugins/modules/azure_rm_subnet_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "781c564f40087d071942dab53c627fed093764c5a244744874e2226ec174bee8", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_securitygroup/aliases", + "name": "plugins/modules/azure_rm_virtualwan.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a390a5b729f05cbb0f6d91d7d663389c81a571a34bd2e931dc56fcdaee025754", + "chksum_sha256": "8586d543fd6b8ede929df540ee4d972c2dfb66fe775726f19f7b5c52a94dc029", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_securitygroup/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_deployment_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2b2f239c18ae7533a69c8a3e380840171bedc20dc4330ffb0b0f14c9cc5bda25", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_securitygroup/tasks/main.yml", + "name": "plugins/modules/azure_rm_virtualmachine_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "436bac9c55273b36de74ec81c5c41e2c608843665dfec86ef85138d81a3c5b55", + "chksum_sha256": "3dc5595ff2ae8fd54fb291396a6b1a07b81fbc0454fe6e9d9e7055b4520324fb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_manageddisk", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_postgresqldatabase.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e1d1f0a296460cb6a411cc926cff5476be07b16ced01f7b9a95e64802dacf9e2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_manageddisk/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_postgresqlflexiblefirewallrule_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a2dfe20b3135c2aabee049f886eaa54f797b5168ae6ed2bd579e7bbc63c21d76", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_manageddisk/meta/main.yml", + "name": "plugins/modules/azure_rm_aksagentpoolversion_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "69fd5ecafb1b4dee2cbcb17f9b767f3fff6a9d717ca8548dec4f9735f3d213d6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_manageddisk/aliases", + "name": "plugins/modules/azure_rm_devtestlab_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b79d487ac5f66f90cfba1e03eb40daf31086e77447861b1cf4aeceee77d9745b", + "chksum_sha256": "973d2a0d1ad46717f41e2bb26169ad1eced874c034068674131ab480b7d496ed", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_manageddisk/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_containerinstance_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ab1aa37508addc2bf616e2c13664f2a1e5e0235af91db2bb84542449d01fc67b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_manageddisk/tasks/main.yml", + "name": "plugins/modules/azure_rm_datafactory.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c8decdddddd8660e19da01320399ff9e5216c7733d9c755a9f812f81068f7ca5", + "chksum_sha256": "5e54eadbb395d175730960b6e089b78c76cefeebe08dca0ab1ae80e4d34e78fb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vpnsite", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_sqlserver_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "31710e981ec3af5a7ab221d4679e06e7d7baad4e1cca7a1e9809536cf07c8899", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vpnsite/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_virtualwan_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3e7d2fdf7181de1499b68196f176080a9563767764ee9bb27bf3e3411cb87a75", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vpnsite/meta/main.yml", + "name": "plugins/modules/azure_rm_registrationassignment.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "46371a2648227e97d625dbc25bdf9bdfac600b28b1fe2c07aa832186562dbe7a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vpnsite/aliases", + "name": "plugins/modules/azure_rm_roledefinition.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "51bfa0d69b7c8b7e94b28aa9c60c921ace3971f50a385673a66791c31749678a", + "chksum_sha256": "1f4fe12f44e9e0b030fc051e90e76d2f0383f4426331ebf72dd0a806cb32f580", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vpnsite/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_aksagentpool.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "35eede66b4539d8ebfabaeba04dc70f75614d3bc94b2d19a721b527269e44404", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_vpnsite/tasks/main.yml", + "name": "plugins/modules/azure_rm_mariadbserver.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bcfd0915de197ad7e6d01dd27e5ffe2a8f62d93303f19d5e4c09373a82dc7334", + "chksum_sha256": "6c671f81b7aff21b252b4844b16135a8fef889b340f66337e394d87e249e4a28", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_gallery", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_trafficmanagerprofile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4df5198ca3361e221f283b8d1cc1d26dbb3ea265422c76ebb8d6357ab6b4d4b6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_gallery/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_mysqlconfiguration_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d9e284a3a0c4c2ec47a44ac4a7419358ab7d897488fa29de3ae616cfed56ec4d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_gallery/meta/main.yml", + "name": "plugins/modules/azure_rm_galleryimage.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "ef785f694e97dfe2e003f9977873c77a3b0e68306bb9567cc6a366a3ff50e293", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_gallery/aliases", + "name": "plugins/modules/azure_rm_hdinsightcluster.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e676d2331077a7a453c2694fef48b0b56195d00e5a1009e3f668a7e174abd16b", + "chksum_sha256": "56f82f0e1dece88b1eb6f238dd564ec67d93ed521cc437233c41e805a2ce0bbc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_gallery/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_aks.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d63a516ee5a970d80bea017097e3d474a59b34c0dc58f0d0ecaced542dfbb5fa", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_gallery/tasks/main.yml", + "name": "plugins/modules/azure_rm_servicebustopic.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "22d0d3850e426784e4df1c303a1857ea5cbaf9735e5ed6df62442ac04aba5216", + "chksum_sha256": "3061e6f04b67b71c3c7d09566a35916f130745ffc7dd1b472385d78587140da3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnsrecordset", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_sqlmanagedinstance.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0658e86bcee4a16b909a105ee7cf17f650924bc8e97c7bc24edde9a6f0d83a68", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnsrecordset/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_cognitivesearch_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8e5e926aea80ecc40b2a0c06745ed85287f4f6f83692af2ad78e7ea641c8d463", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnsrecordset/meta/main.yml", + "name": "plugins/modules/azure_rm_postgresqlserver.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "665e6153c4700277d41a5b0b83a65601d71b3088868f8e8f93229b91a3d660b1", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnsrecordset/aliases", + "name": "plugins/modules/azure_rm_account_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "36614727374728e26b5686e9fac66641e5b9c268b6945f2dcd1b4a9c4d2232c3", + "chksum_sha256": "4ec8a4640333983bf88ff274ac7eb854329844cf696447b2ce9cdc070e9a093b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnsrecordset/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_vmbackuppolicy_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1493048fce1c74d200efa796b75048be8562b854ce5211f2f8988c7ead43988a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_dnsrecordset/tasks/main.yml", + "name": "plugins/modules/azure_rm_devtestlabenvironment.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "9d766be151f93042b7018bd39ac79b987e66389613ce426a70d5683952b5a841", + "chksum_sha256": "011a6997e971c489b239d38a889ed0bbf2c90513ebec62aadd64f0ca736e69a5", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageaccount", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_appgateway.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b0a80426b79eeeb00b8ab51935f167eaad07d2887d8d1e3298b0a181e9ce526a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageaccount/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "abf1007b4b27cf62007827926b3494ca4fadd27670cdef0c8e6d965dafd6e0f5", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageaccount/meta/main.yml", + "name": "plugins/modules/azure_rm_appserviceplan_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "2feccbb74790330b291a4ab0f8bcf3d4ba44f5bd2c18490aff02c92f3d043e09", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageaccount/aliases", + "name": "plugins/modules/azure_rm_routetable.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", + "chksum_sha256": "903a9d84fb9a4c7aac19a8c54c32e414e364570fe6d02b56427b8c9a8263e979", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageaccount/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_openshiftmanagedcluster_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cfea70f6d3c1cb3fe2a04e7a06d9887a6d9b95ae68015f2455cde00bb48b8844", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageaccount/tasks/main.yml", + "name": "plugins/modules/azure_rm_devtestlabenvironment_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cddf19a5eb8e886612cfea1a81f43967228e1375327c04e984a143e6bf5d495f", + "chksum_sha256": "1b274684226da721ee03fdd590bb307709565a0a989ddb1a409a07db7c3b2e50", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mysqlserver", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_containerregistrytag.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9b6a6b029d0bff63cc6fd9cbbbc92f44337fd23d460747b942a4caf32731ad05", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mysqlserver/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_privatednszone.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c4def272c347cc85f0e108b4392b69eabd6e9caf432cbb84b2acc902bd8a3f34", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mysqlserver/meta/main.yml", + "name": "plugins/modules/azure_rm_iothub_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "5ceef9d30aeb4826188b1c96a6d955955e99ae90a1e8b9ff437859f82a3cdd5a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mysqlserver/aliases", + "name": "plugins/modules/azure_rm_virtualmachineimage_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2c74420c4bc9cc5d8af14406a1d97ea762c6b8afa4de8728a4a833b2e742cf41", + "chksum_sha256": "81e679d55f2d54420d960d51e6f0318cec3b781dd37a062df0b0ff9e1756797e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mysqlserver/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_monitorlogprofile.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "0951e10121e28230e99e7a3143ce444c9bc4cbf8b7858033c6dd5d071e1ac579", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_mysqlserver/tasks/main.yml", + "name": "plugins/modules/azure_rm_postgresqlflexibledatabase_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "743277ee9a1eda331e62acae9a94ba4820d4bef31de88a77008d62fdda27874c", + "chksum_sha256": "e0e60a876bea1ad5af26ff70972b0ee0ada7f8435b51cb0a679ffd08f90212f6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_expressroute", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_apimanagement_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a7b9f6fe7e3fcd0a532ae601c02a53d45ddeddd5625d9b2747c33b0a653cdccc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_expressroute/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_devtestlab.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2ee7422c462798a4b45173196c63c87773a6e863597e2aaa80608102d0e4d497", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_expressroute/meta/main.yml", + "name": "plugins/modules/azure_rm_devtestlabarmtemplate_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "92ab9069e528f924357f86307b0e0714d26a089381fe7ae5a833bd1a07071fc7", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_expressroute/aliases", + "name": "plugins/modules/azure_rm_keyvaultsecret.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", + "chksum_sha256": "11ac0f42fd18e2f8480376dc2021d461cbe09bd15464c089a5863ea09953b157", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_expressroute/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_galleryimageversion.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5696dced8e1885d7512b1289d87a9165d65071b8f7dfad7fa3d172d1e00b354f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_expressroute/tasks/main.yml", + "name": "plugins/modules/azure_rm_availabilityset.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0fee3fb92d49fcebdc6564a4becd35f638cfa294e5d893fc5adf2fff21ac072b", + "chksum_sha256": "685bb7c2dfeaac6f1042b164d014064dcad6b8865cbe764da3ea9ab5f23a9a76", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_devtestlab", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_hdinsightcluster_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "735371a6bed2621d8a08ad8abe4e12b69d20295357f75f59988706d7115bf8e2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_devtestlab/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_mariadbdatabase.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f8dc569f2de810f80a09d827c276f44fd85dc254766b82bed9769846f41008b6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_devtestlab/meta/main.yml", + "name": "plugins/modules/azure_rm_sshpublickey_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "b02d533ef59cd58cdc9668f7f5eda1b7df55d75f0c56293fcd8ba50c2f39aebb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_devtestlab/aliases", + "name": "plugins/modules/azure_rm_virtualnetworkpeering.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "435162ac2df7aa373bc2d191a07d79c283d3891a1278b0277f85e6112b96fc03", + "chksum_sha256": "f0ee463d7cbde4f3c704542e0ff6e8220b22f436b1014b15a355e8c832845ffd", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_devtestlab/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_privatelinkservice.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5c56fae085180b9c34424f1cb9fce62adaac67e7107f556702f1a8b9ae00025a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_devtestlab/tasks/main.yml", + "name": "plugins/modules/azure_rm_webappvnetconnection.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "17fd6c08f41838809e461f199a62e373c8bf28c5d90199bf09340ae9762dd252", + "chksum_sha256": "5f823a8fd9802af336c53b103f05d687a20989e92334d7bc122f7ccb62a6a410", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageshare", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_natgateway_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "05d862d157fc493cab345fea70f17c3913624364407562a9a2d884377f69f586", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageshare/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_appgateway_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fbe1b90752ce94a33ab1c3e6771f90e4fe87d676e99819e15da631fe5fe2cea5", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageshare/meta/main.yml", + "name": "plugins/modules/azure_rm_postgresqldatabase_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "3c896791d9f215a0ab5c7cb5315bcc302392ba07eea4081b4c68cf392c7013c2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageshare/aliases", + "name": "plugins/modules/azure_rm_mariadbconfiguration_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", + "chksum_sha256": "783f344263d15fef8444cab2f98286515b584c64945f759d1c45ab3363ae1304", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageshare/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_storageaccount_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3bd4cbd10fcd4f1ea3c79e717e5323436f9bea1f0f49000015d098ba01ba943e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageshare/tasks/main.yml", + "name": "plugins/modules/azure_rm_publicipaddress_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8428a40d80a569d0c5ac929641e4befc59b86cf7c7cc4da72add3b5eb4570202", + "chksum_sha256": "7c60893a6d181b60254e2b8e2dca0aae0c83c1f98bf2e1a6f2ab6206a222112f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistry", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_deployment.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2d452a372b394707323cee58c3d480e0510b8cc45d962dc7412c00ac96d58fe6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistry/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_galleryimage_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "fe094e6c2005824059c1dc30f851d8c0df973c8f75148f1f1a3b7ed7a69bb262", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistry/meta/main.yml", + "name": "plugins/modules/azure_rm_storageshare_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "c30615415440ade0b39196ccd619a923cfce2162548c18c7edaec635f46e84e3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistry/aliases", + "name": "plugins/modules/azure_rm_sqlfirewallrule.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ec1ff0ecb096def7880d4a1aab74cae1ee3e46dbdba9df7f476b7311ee64f2ab", + "chksum_sha256": "bf215ff5460bd7561374c1013e93dd13406286bedf9bb34fe5c63a423d65b996", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistry/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_expressroute_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "5e302a549f10b209ec9b8d61051f3ddf478eea0e4d99d8eb9af1db568975994f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_containerregistry/tasks/main.yml", + "name": "plugins/modules/azure_rm_availabilityset_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7eab7dde3b4ad416e882a673e1b671770c760c1d2ff97f9c21606a24bb3a7540", + "chksum_sha256": "5210c3fbf5fd2f5b702cd82ba5cf7b44604231bebbe9f00a71ee71616a8e2e6b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_acs", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_sqldatabase_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d97f650c2b9d89769f4089c17e2d64c1ee066e5295e757119f270be7be10b25a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_acs/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_webapp.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3905f0d95ea3661bb716b8b1f6c7d0806ce92cb5eeec61824d0ec8657d75824f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_acs/meta/main.yml", + "name": "plugins/modules/azure_rm_eventhub.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "aeadcc0ec44f966ae318556be223ecbbe4198c412c9d34d1360d724aa919ce0e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_acs/aliases", + "name": "plugins/modules/azure_rm_postgresqlflexibleserver_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2f7e954a810d0341b1aed1d34e5684bc502980bb6ebbe6a46fb03163ed0e11db", + "chksum_sha256": "8be887b3634bf62a040d6ffbb5d1d5317d672761144d3967856a574cac4c7f17", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_acs/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_servicebustopicsubscription.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7ffbac3a815640add669c05c8c29d78ac433ccd8e9762540746eef25457f6829", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_acs/tasks/main.yml", + "name": "plugins/modules/azure_rm_sshpublickey.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ecad2cdce0986a34a8f64d2bcbcbd742d99a0083d4e2773cc6a5482a5d529b9c", + "chksum_sha256": "b30925c6282e8eeb24532186779ef38ea30a1780f6ac2baf52b0d8d2f1380bbe", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageblob", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_virtualnetworkpeering_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "70b548cc3d9362d2c6a3c0ddedbded5ec61be98334bb43d0c59cad8a95065898", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageblob/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_devtestlabcustomimage_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b7cee683acac28bef8c299a125222c4f9d7ec64ebc9a56a3ae8aacc698d3a09b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageblob/meta/main.yml", + "name": "plugins/modules/azure_rm_adpassword_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "133c3630a9e91f45a7c86c05453240143d77f15f0bc985bd8c36128821ae4b3d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageblob/aliases", + "name": "plugins/modules/azure_rm_vpnsite.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "109bb8ece8ca54a061f03f7050aca3401610606b79a6e313d2556dcb04fda637", + "chksum_sha256": "6f61d4a29a0d5b8270df41060245bdcd633e9b6d16e388cc97e19c828578872b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageblob/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_apimanagementservice_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ed595234eeeeafd2c72aefcafbf6d13d86d057bfab2a41ae8b31b2690d74a2ff", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageblob/tasks/main.yml", + "name": "plugins/modules/azure_rm_virtualmachineextension.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b93536f3d35eaa0d49a0bfb1ce75902b524b86c0db95f3e43122088dcfcac442", + "chksum_sha256": "09bd02e50c12aa9e602e8ac7b4312b2619be27b656114309625c9aa39fbcb97a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageblob/files", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_mysqldatabase_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "942d9a275c4bee8ba4ee32eb8e025eec7f3b70e6a52fce3602631c1cce6884ae", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_storageblob/files/Ratings.png", + "name": "plugins/modules/azure_rm_route.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "20cdf86ae984fb64eefdc57a0e03f34c83cb8b27834b33c84768cc2b62cf9d68", + "chksum_sha256": "f290a0e704d3225c8689ac3a7a9523facc263adace73b8193906cb5ee94bffbd", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loganalyticsworkspace", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_mariadbserver_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3b836969fea8c255c6aeddca297111eef43141755a9b61677661dd581bb2f1a4", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_image_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c6dfd163560a3389f0d12d364e61a5a6e6bb87f50b2fc08965b19285002b600d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/meta/main.yml", + "name": "plugins/modules/azure_rm_vmssnetworkinterface_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "968c1e5781fdca422d62eeea87dd9ac45132e5f03c7e3a91ca6b15d0683eb944", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/aliases", + "name": "plugins/modules/azure_rm_sqlelasticpool_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f6ab21fb1deaf7061dd270b8ca0bf7c6e585eac172153559349e997150abbcaf", + "chksum_sha256": "05959ef86783c8274fe64c2c1cec19208c37b3d038e6556ffb3a20b51813375c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_devtestlabpolicy_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8fcaf07dfe338c84a604855e61c4ad63061ed6e855ef5faf9edb34683d4f26a9", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_loganalyticsworkspace/tasks/main.yml", + "name": "plugins/modules/azure_rm_publicipprefix.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "529ae2dab2d63d3af2eab9ff5fe9b466a9c2bf3bf600d0a5221126ddec9be288", + "chksum_sha256": "fd96262bbb96e29f08befba0e8ce69102066161089584b8cdf2f3ab6789fb6fc", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backupazurevm", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_cdnendpoint_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4311037a5b5f1a98e3c03b7fa222f259e996783695c05fc0409990f95aa2dacb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backupazurevm/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_hostgroup.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7f3b26f577bb53702d0ed884da4c0c587dc6a186b7bdf9b87d3765c7dadcd89f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backupazurevm/meta/main.yml", + "name": "plugins/modules/azure_rm_containerregistry_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "b176c5d28ade7bb04fb50a82ea0c59987cc004136fcfc37a50cfa240d8c29cc3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backupazurevm/aliases", + "name": "plugins/modules/azure_rm_aksupgrade_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "91c612e6c7b96f80e7e1cede3dc0ef7431a2900356b7e85a7521e2679bfcfa49", + "chksum_sha256": "e40923a0ba91ba10ec91ccd2960c60501d5e60c0287ab2578c66d756b865409f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backupazurevm/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_containerregistrywebhook_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "18b7a6844956e67318fe818bdafd0c94d6631657ec33d529e721e6e21b18ed89", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_backupazurevm/tasks/main.yml", + "name": "plugins/modules/azure_rm_diskencryptionset_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "4ac0d2995ac62544c567223a1e45c1b1fc568b840b645d5b42a0b41fd4df1661", + "chksum_sha256": "586109c40b10714b5280368db2802fca8d4fc87f797e2b0d5084bb5e7a4df3df", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationdefinition", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_devtestlabschedule.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b91018d718d35f6ce1b2e911281a31e747c5548db725d8d7b211418a2cb18fb8", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationdefinition/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_recoveryservicesvault.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "91dd5cad76a70a786d62389117df58963ac794a6b4d6161c87461d067c168075", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationdefinition/meta/main.yml", + "name": "plugins/modules/azure_rm_postgresqlfirewallrule.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "6a0ef8e59ec7d273bd94d6e8e40f6ffe8e0a313f8e8d912b9ecb71c5db6ea662", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationdefinition/aliases", + "name": "plugins/modules/azure_rm_aksagentpool_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", + "chksum_sha256": "92c6e3a0f537164ae87f3cf64dd071238a5c8349d7ca84a16826720fc5b82e44", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationdefinition/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_adserviceprincipal_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "86743f28d6f9e141baae174641bd0b23f8f577ac3a4b2696a72cdd709dd765ff", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_registrationdefinition/tasks/main.yml", + "name": "plugins/modules/azure_rm_privatednsrecordset_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b1e2343656426831e5aadf56883b897f520bfc13adee76347b787f396f037855", + "chksum_sha256": "ca64fe771c93ee29952634b1acd63d8ae35c0f36b4ef3a33f6ac1ef0994e2e42", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_availabilityset", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_webappvnetconnection_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "cbb81f50bdad8e9d738f6a8ff9566898df41fec03e92e3b03383228de5607fff", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_availabilityset/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_keyvault.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "e4a7cf6ffe8993e17dbb9030bfec0c91eba08c6a15f3b040bde6217a6803f777", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_availabilityset/meta/main.yml", + "name": "plugins/modules/azure_rm_image.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "a4648f6095259498761c468442ee994954306f5a112c89ed427e4381dd1b9447", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_availabilityset/aliases", + "name": "plugins/modules/azure_rm_openshiftmanagedclusterkubeconfig_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "5647901b6198849a4dd58b7fb51aee85b889220f80acde88cea67bffff453d8d", + "chksum_sha256": "611955771172bb4644da4c97ee0c5131b303bcb301677e636f55f3ee9df3abfe", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_availabilityset/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_webappaccessrestriction.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "a31793686f398ccb3ea7c32aad8341b808e06449bfe5ed468303d74a5406cf2a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_availabilityset/tasks/main.yml", + "name": "plugins/modules/azure_rm_privatednszonelink.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "0d096b5b5000fd2c1c259adae048dd6ac824c2441db10e6fe352282c8bb77b8a", + "chksum_sha256": "4166cc9a7e671531be63455046c657896ef9ec1e35a84f7c9bf5bc39cd50bf11", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hdinsightcluster", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_networkinterface_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "690d8bf0ccb1e6f3ab2587ff071b31132e60dfee385d10fde3347b7f0514f364", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hdinsightcluster/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_automationaccount_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "048a0c9b532196427437575202beaf31f8314efb70c67aa86733e6cccc14a98c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hdinsightcluster/meta/main.yml", + "name": "plugins/modules/azure_rm_registrationdefinition_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "4b48937ab648dae2d339e1d1975b2e6562fbfb25b5b3789ca1c3295352963b22", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hdinsightcluster/aliases", + "name": "plugins/modules/azure_rm_aduser.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "dffdf5ca6061cf1a43744d6b7e0bb18a4020eed3f693702082b2314f982c65a6", + "chksum_sha256": "f455cefd4a7af853f672ef7bffbc09422cd9f659841ac35ddc60a4a29c5cde65", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hdinsightcluster/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_loadbalancer.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "40bcb2a088750276d350e5170a7993a5e92117948835d6bd30dcf5989db2cf11", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_hdinsightcluster/tasks/main.yml", + "name": "plugins/modules/azure_rm_datalakestore_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "2a0464f133b840983fad3fa552279ac8aca4a07023877e84bd273e8bde440f65", + "chksum_sha256": "64ced3d20472f4e29c76baed328f40e9bc1483583f04fbf7e69e9346b5ed07ad", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappvnetconnection", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_multiplemanageddisks.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "95a1386da7e22dc74338466668e3542f37584f4272481fc56b298ee95053d23e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappvnetconnection/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_resource.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1c0e218be7f687e3d53c7b051293c6721071318582dada5c295b7cbc2420489d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappvnetconnection/meta/main.yml", + "name": "plugins/modules/azure_rm_backuppolicy.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "37cfea022ca13c6ea40025ae4ec9d00f9e962fba506e1a5708bc00dcfcdc9116", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappvnetconnection/aliases", + "name": "plugins/modules/azure_rm_virtualmachinescaleset_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "262ad6ab8a8087f2f21d4f26a2c2d02c347a7edf0fb1af8fdb931ab1c1087bbb", + "chksum_sha256": "5925fb4d64f27c1460dc96e40aaa1eabda5612174aa598a717856b2861540662", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappvnetconnection/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_sqldatabase.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "4ad23bc0505f7a62a03434a0c94c2eaf90ed06c4d5e4ccbf05f169de465fd693", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_webappvnetconnection/tasks/main.yml", + "name": "plugins/modules/azure_rm_dnsrecordset.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "fe11d34bfc4836a138318153cd0df0bb89f64d2d6d64f9dc7843704f1bd60760", + "chksum_sha256": "291de8eb7d89ed612be3a3777aae9f947339745011f5f513cb14925f375c55a3", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_networkinterface", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d79dad68277ae5d3c8c72e1265606e28b17e19c26d2dd94452723a08b22e490d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_networkinterface/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_vpnsitelink_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c12058e056680201ef2358025ed148b9338a50eebace5b8784cc9acdc525093f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_networkinterface/meta/main.yml", + "name": "plugins/modules/azure_rm_containerregistrytag_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "99cde6ea4e4b3f5216131583a7f2ce0dc1777e836d93089733da276895c65b44", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_networkinterface/aliases", + "name": "plugins/modules/azure_rm_virtualmachinescalesetinstance.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "79cafc6b10612f907e2e4a97bac50c9948ac0a0dd5030875a9465204a6323b48", + "chksum_sha256": "29c4528fce1aea43abda1fed65f9d49ef13b592592174c2305fd581e62cdcf8d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_networkinterface/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_storageaccount.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d09f22958e853cdcda49fe673df53310e1823dbae741054fe46f8cc8a8044b92", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_networkinterface/tasks/main.yml", + "name": "plugins/modules/azure_rm_hostgroup_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cd2b9fd7ff5b256d26839ba3646b9347fa95f8fd6b1104e7f2835e1d7b7b2624", + "chksum_sha256": "05d3069e290c810fe454923e22f4aae4932aa8924b12d872039904d87b779a07", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednsrecordset", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_containerregistry.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "781782bcf6811e28b975d35abb3892b96dbf168421891a06e352d02ac4c00569", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednsrecordset/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_proximityplacementgroup_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "3e049bd091a4b88b2d68b6462d3cc15d740fcc65f5d3e310496513be40a83661", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednsrecordset/meta/main.yml", + "name": "plugins/modules/azure_rm_resource_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "81d9773dc10d0f9db2f733a4f85972dd8bfe7542c5f75a9672921559e2adbd2d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednsrecordset/aliases", + "name": "plugins/modules/azure_rm_virtualmachinesize_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "36614727374728e26b5686e9fac66641e5b9c268b6945f2dcd1b4a9c4d2232c3", + "chksum_sha256": "24e4730a6256f17cd27877328ed90580bcd2ac93c1b3718b70e18d8c574769a5", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednsrecordset/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_registrationassignment_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ac05497040ab2ad0a62d8b284128375cdf7bf2953572d5f08e3d125c8adacfbb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednsrecordset/tasks/main.yml", + "name": "plugins/modules/azure_rm_managementgroup_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1fc82f73aab3fbd25c62ca6e740a796a286df28c3de2cc6d084619cdb7fd12eb", + "chksum_sha256": "728bb535e8dbf3211e4a79123dfa981434dc51423efb046e2bfa6cb35c5949f6", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_proximityplacementgroup", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_datalakestore.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "da55af371c87610112c5ff6dd9d8a1c1e3fa38ffd2e3bf8d7887f9a0dfdfd03b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_proximityplacementgroup/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_adapplication.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "49e82eb39f31d45623c7713aa5e6f1a8ed2cb7eeffbd6eeca67a19ac8283687a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_proximityplacementgroup/meta/main.yml", + "name": "plugins/modules/azure_rm_servicebusqueue.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "5ba3c26da0e1437c64c3a7d945886563965b08c9fef67f099e97990ef5f50290", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_proximityplacementgroup/aliases", + "name": "plugins/modules/azure_rm_loganalyticsworkspace_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", + "chksum_sha256": "b2ea8f5bf029879cd6b7367c7c07d1f638453ff39e0c9f64c04db9afa3a57f8b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_proximityplacementgroup/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_postgresqlflexibleconfiguration_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "aaf618321aeed34343058f7278967fe2290250cfdfa525eb75fd431e2fd830fb", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_proximityplacementgroup/tasks/main.yml", + "name": "plugins/modules/azure_rm_monitordiagnosticsetting.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c5c88276931feb2e7c2b7386c1ed4885d19888d5f70cf8c76dd4088fa33fa79d", + "chksum_sha256": "a87a1032899109683876d6a6ce5eba1ee931f2c64442c0910d69242a05560b26", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resourcegroup", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_devtestlabschedule_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "d421b64fef84568f67d602785f1529be85f0dc8650450fe132797b24df7b5424", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resourcegroup/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_servicebus.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f7379123759b383d1c9b39442ddff6beb7910e1bb6c68ba570a8d59eed2c6e95", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resourcegroup/meta/main.yml", + "name": "plugins/modules/azure_rm_managementgroup.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "b327ba44e77b9ab0f30dd21b28a1dbcd750994b3ffb7a55fb96ea057a0378a7c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resourcegroup/aliases", + "name": "plugins/modules/azure_rm_trafficmanagerendpoint.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "cd30933c00554775a36ee6421935b7d8baf776db7cb35d5a103be9e18b7d2486", + "chksum_sha256": "48772694d9d17d8d0f6b0e6d44c4359dbb35861116c38fa933b0db93981f7a76", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resourcegroup/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_postgresqlserver_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "41eccd6933ff71ce9f0bbfe939057aeea30beaf4c6e475887a7bf21df6a48f67", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_resourcegroup/tasks/main.yml", + "name": "plugins/modules/azure_rm_devtestlabvirtualmachine.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "ccf92a54443b6b7b1df4139247acd0d9496fb6266d6a99defb4035fb76cb61a3", + "chksum_sha256": "01373d3450d1449d03df275df6f2c64b6e067082e5a4ba0c5c6fa569224e58ee", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhub", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_postgresqlflexiblefirewallrule.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8db7ef3ea60e698e7b5a65be465d6a639927cc63d91a2da61e1cb6a5f89fe7b8", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhub/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_containerregistrywebhook.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b911199637d90fb213eaf63e586745cfb8ab889af2f199340d0d4df59138362a", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhub/meta/main.yml", + "name": "plugins/modules/azure_rm_eventhub_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "840c5f5441849b9ae7c489f04bb2fd065cc4192ca4a8143c1fc052c2845e002f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhub/aliases", + "name": "plugins/modules/azure_rm_ipgroup_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b09e7a20443d9fe8e820607cf9ae826988c41fe890af049d025cb7eba9e4dbb0", + "chksum_sha256": "dcb8c2107767aeeae8dad3a39e68b5a1c475d9eb91e0a9c72b3276461fe0f4cd", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhub/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_trafficmanagerprofile_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b99d27f1679a3d1fafdec74448bfdf2977930e8cef05f0b6d720971b4f6b8c8d", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_virtualhub/tasks/main.yml", + "name": "plugins/modules/azure_rm_vpnsite_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8810084bf5132a43f31c425b77e96134af6d5855dcb4d4ab94ed2b691d555614", + "chksum_sha256": "63c87ba7508bb5c7e2f4968c4975b8e85e27260474dcb6f7d558295f9c56a946", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszone", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_registrationdefinition.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "01e4ec5adaaf634de07a9d34c5ca56639c5dd57d45c2a713dd6d563553a1dd3f", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszone/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_mariadbfirewallrule_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "7a2b125c6e0ed19d1fe70703e24ed9e4257713c492e927785fe35cdf789afcc2", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszone/meta/main.yml", + "name": "plugins/modules/azure_rm_mysqlserver_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "595b1221845b1ff1d61c133eabb34930f9e9d0b59cd2ee853cddc487b182c57b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszone/aliases", + "name": "plugins/modules/azure_rm_adgroup_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e131092efb0e9d778baeb38471a15da9b4f8ab9e3425ec4f37aaece309220d47", + "chksum_sha256": "c2802b5f00ffe0edaf458e13a4929c6949f61d4d75e1d2b965445eb923fdf206", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszone/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_gallery.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "9834bdff67c806952f4147583348ae861ea7a1b28eb9e2f153d9b7a5d9060bce", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_privatednszone/tasks/main.yml", + "name": "plugins/modules/azure_rm_devtestlabvirtualnetwork.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "b2de5836a16a64f95f0494dd53d54cd82716c1133e7707c0c2680d9502dfef5c", + "chksum_sha256": "ba592f55f40cb7fa8986e924b493a8e8341db4f399085a963c488aef11626367", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datafactory", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_trafficmanagerendpoint_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "19fa3f18fc08a32e65b2dfb6c0b74a7a4827a2afcb36409214de9887899e754e", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datafactory/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_aksversion_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f5996a6bb0e520450296272e726d0c65a1b58fed9d780c0c9dbd2edbb8e31377", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datafactory/meta/main.yml", + "name": "plugins/modules/azure_rm_expressroute.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "d00bd90476595ae7d97d3ca8f8aa7ff475ebc3dd87d7d12e862bf0527f7bd81f", + "chksum_sha256": "b7a0f0dd5862dbb3fc72329ed7c6790cc18a79e279a3e3f85896c075dda2ab1c", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datafactory/aliases", + "name": "plugins/modules/azure_rm_webappslot.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a74040b53394bd68b1885c350f1f62603740e721ca38e01609660895693a3858", + "chksum_sha256": "d7c28a3338c7a7ecfa0da50def079ab83286aa1750aa52d13944fbac4fbf2399", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datafactory/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_functionapp.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "b36955b4ade5a066cf353dc80387fb9e7419fabf07664db38510b29c6931282b", "format": 1 }, { - "name": "tests/integration/targets/azure_rm_datafactory/tasks/main.yml", + "name": "plugins/modules/azure_rm_loganalyticsworkspace.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "eedba69010cd9dad1b57c7e0f7f18eacb0feb43359922cb53c3ba98479e8dfcc", + "chksum_sha256": "5f5d8fa3f00c30d80ce2427ccb7c9d8a00e78c255ecfc67fb1de5f37256c3418", "format": 1 }, { - "name": "tests/sanity", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_securitygroup.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "2b34dfe1c061f8745f84de518f66d0eb9a81d9c033240953ae63e31ebe7f2161", "format": 1 }, { - "name": "tests/sanity/ignore-2.13.txt", + "name": "plugins/modules/azure_rm_devtestlabvirtualmachine_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c88d45d86600e17b8da638521ccef69e6f48ce4a0e1486cb59e09ae1d0d65d57", + "chksum_sha256": "37c4b6bc2ca17c75ce12edccfce27959e1f157ed0bf72a78184b8293e96a0d11", "format": 1 }, { - "name": "tests/sanity/ignore-2.15.txt", + "name": "plugins/modules/azure_rm_devtestlabartifactsource_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c88d45d86600e17b8da638521ccef69e6f48ce4a0e1486cb59e09ae1d0d65d57", + "chksum_sha256": "7b31a9bbe98afcb5510621d353069923e449532df0b4e01de5e4fc3b7f421f6b", "format": 1 }, { - "name": "tests/sanity/ignore-2.14.txt", + "name": "plugins/modules/azure_rm_accesstoken_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c88d45d86600e17b8da638521ccef69e6f48ce4a0e1486cb59e09ae1d0d65d57", + "chksum_sha256": "05f2949f236a8f79c474c1caa57df258695e9f0a87f9072abe4aef9ca1d323d6", "format": 1 }, { - "name": "LICENSE", + "name": "plugins/modules/azure_rm_privateendpoint.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "8b1ba204bb69a0ade2bfcf65ef294a920f6bb361b317dba43c7ef29d96332b9b", + "chksum_sha256": "9cf71bc67a11a058b6eac5f7c06c3a003ecce968f6fe09285f43dbd81f91fdf9", "format": 1 }, { - "name": "sanity-requirements-azure.txt", + "name": "plugins/modules/azure_rm_virtualhubconnection.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "bd3de2a9921f5fcdfed1582123c18a91bd48b120d2e9c10d9879ef46d40e98f1", + "chksum_sha256": "2b3ba5bbf31b9e64c4e0978fa92768ce9115fe39450f5dd8085c775fe4ed2716", "format": 1 }, { - "name": "CHANGELOG.md", + "name": "plugins/modules/azure_rm_batchaccount.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "7f464028041360717ad63fbeeb1a50c208c8d1c13792f1ac55f9aed2449af8da", + "chksum_sha256": "8da700f46228d2eda7ba617acfa096136ad1cf5923cb44ca9ea2e67c6ef0bbd0", "format": 1 }, { - "name": "release-pipelines.yml", + "name": "plugins/modules/azure_rm_mariadbconfiguration.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "26a84e5d665443b05c84c798e9d901a7681cf891436e04b4a16c9f9cfbab1f8a", + "chksum_sha256": "f54c337f3d115d08dcac88d6e4fe16ef1db3d9dec1833b033928f227d89ea11b", "format": 1 }, { - "name": "CONTRIBUTING.md", + "name": "plugins/modules/azure_rm_privatednszonelink_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "290a3dfba9b53aecbf86badacfdcb7f320c9a924e02a8f0b4824785a551d0a39", + "chksum_sha256": "93d488b4238c4631765dff43c9a6978f3bef9d8ff35294dba4f34772a85a4284", "format": 1 }, { - "name": ".idea", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, + "name": "plugins/modules/azure_rm_backupazurevm_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "f347194586ae27419cecae08bec9340ce537b9c9eeb8bf785d25db8b60c99525", + "format": 1 + }, + { + "name": "plugins/modules/azure_rm_servicebussaspolicy.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "10d85532d9875ac3da016f15add256df6cf2cbb8a88d4a57ad316bce7df7a45c", "format": 1 }, { - "name": ".idea/misc.xml", + "name": "plugins/modules/azure_rm_rediscache_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "e5df86803b5913746c8d40c348879d7f9442e4a6bfefbae93cc711a640fba506", + "chksum_sha256": "a10c697c6832b6d01d4c3645819ee5a8f254715d5b5ac4bdd8db94dbe8fa5602", "format": 1 }, { - "name": ".idea/azcollection.iml", + "name": "plugins/modules/azure_rm_lock_info.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "a9e614b7294d32d9dd7d25fd7116079ac7e3ac6bbe3043f672cb3db0f828eeeb", + "chksum_sha256": "7e2b1cfcf35b517ad440bbb1457931c7481b5fd442e3f4fbd8a3710c549ac9a0", "format": 1 }, { - "name": ".idea/modules.xml", + "name": "plugins/modules/azure_rm_virtualmachinescalesetextension.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "c8aa540922a578f85297bfb3bacf703eb49b573c6c229fc2323e6a90e33bdca6", + "chksum_sha256": "a8ef46432cfcc51726f0e9d1ce8003a5e9820432a253d897b420c8423c178f74", "format": 1 }, { - "name": ".idea/workspace.xml", + "name": "plugins/modules/azure_rm_virtualnetwork.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "f87e05eb5e48aba1dff20dbea0fb919b6f3c848d2391064f56028ae939d7101d", + "chksum_sha256": "d1f54cd77a98a82bbc32959ec20f38af893dc0a41c442c995ed64d42c53ceedc", "format": 1 }, { - "name": ".idea/vcs.xml", + "name": "plugins/modules/azure_rm_devtestlabcustomimage.py", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "62be7e0a7f84ab3c35b4d4bafb890a4951d061eadafde1a10aa3f5d0406db5df", + "chksum_sha256": "9c9f8924ff79fc0b02518ff6a8142c1de2fe7ecf2164665def80420e31cd33e0", "format": 1 }, { - "name": ".idea/inspectionProfiles", + "name": "plugins/modules/azure_rm_bastionhost_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "dcdf18934767abd5f6912ce0bb9cbbff6954c79fab3998fdf9ea3c75f5f9d604", + "format": 1 + }, + { + "name": "plugins/modules/azure_rm_keyvault_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "6f2320d935c3989cf5f0e0fa1b06e87cced44393b5e772310a9c4e6f49c2fc1f", + "format": 1 + }, + { + "name": "plugins/modules/azure_rm_postgresqlconfiguration_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "61b7807ec717db7657e825a2c1bbd815ede63112b9ce0bd4811e1c486ef01fd3", + "format": 1 + }, + { + "name": "plugins/modules/azure_rm_publicipprefix_info.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "c7b5a5d41eff443ad1b8ef21a06d230a559c32f11523f09060ccd3ea1101c933", + "format": 1 + }, + { + "name": "plugins/inventory", "ftype": "dir", "chksum_type": null, "chksum_sha256": null, "format": 1 }, { - "name": ".idea/inspectionProfiles/profiles_settings.xml", + "name": "plugins/inventory/azure_rm.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "47b59006cb06078a81321afbd3b443cb9255af87a78989411a8d42c61f9b66ec", + "format": 1 + }, + { + "name": "plugins/lookup", + "ftype": "dir", + "chksum_type": null, + "chksum_sha256": null, + "format": 1 + }, + { + "name": "plugins/lookup/azure_keyvault_secret.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "80c27a8f8599afe6734f00e807a39e293e3569cf09517d2e09254996fe8c8818", + "format": 1 + }, + { + "name": "plugins/lookup/azure_service_principal_attribute.py", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "32b87b6f2e4b429d14d2f428cb504a73d1e2ab75a36ac99556f58a036ab12c7b", + "format": 1 + }, + { + "name": "CONTRIBUTING.md", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "290a3dfba9b53aecbf86badacfdcb7f320c9a924e02a8f0b4824785a551d0a39", + "format": 1 + }, + { + "name": "azure-pipelines.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "1f55cf75a25502f8322df2fc8640e52f85fed4459b8c26fee3c75295f9c45552", + "format": 1 + }, + { + "name": "CredScanSuppressions.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "6172c5997eeb3cd19c9ca2b5b97d6e2983cdd1fa60b2460d7bbb74055edcaa46", + "chksum_sha256": "98c0ee6a0b7a115787cf109a8c0e2ea4a61df6751ecda37915b22ffb44a1128d", "format": 1 }, { - "name": ".idea/.gitignore", + "name": "sanity-requirements-azure.txt", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "1bfdece3645ed8ed356030f22cc2004dc3f401ff060ac3d24de811c3bcd82e16", + "chksum_sha256": "62326475a7ffd00afcdaf8a3d89158f778593e56e8b694a388daf9f523b53648", "format": 1 }, { "name": ".gitignore", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "702d6332d579931561017161f2d96eb3b023a006c94ed262d789411d0f21bd26", + "chksum_sha256": "38926e151151b0e009deae6bd0bfc42f6ac03c8d1f900d32acc6e3711447f321", + "format": 1 + }, + { + "name": "pr-pipelines.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "ce013c171143675f4d44e20b4b7d3907c5cee12c53f055c2c3bf6edebb1342ea", + "format": 1 + }, + { + "name": "release-pipelines.yml", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "26a84e5d665443b05c84c798e9d901a7681cf891436e04b4a16c9f9cfbab1f8a", + "format": 1 + }, + { + "name": "LICENSE", + "ftype": "file", + "chksum_type": "sha256", + "chksum_sha256": "8b1ba204bb69a0ade2bfcf65ef294a920f6bb361b317dba43c7ef29d96332b9b", "format": 1 } ], diff --git a/ansible_collections/azure/azcollection/MANIFEST.json b/ansible_collections/azure/azcollection/MANIFEST.json index 4c8d77d4a..c78a03285 100644 --- a/ansible_collections/azure/azcollection/MANIFEST.json +++ b/ansible_collections/azure/azcollection/MANIFEST.json @@ -2,7 +2,7 @@ "collection_info": { "namespace": "azure", "name": "azcollection", - "version": "1.19.0", + "version": "2.3.0", "authors": [ "Microsoft <ansible@microsoft.com>" ], @@ -31,7 +31,7 @@ "name": "FILES.json", "ftype": "file", "chksum_type": "sha256", - "chksum_sha256": "3ed7ebc35c6b19227d62f58a00333d40e5ba30ca842d3c2c293465bae42f7b4a", + "chksum_sha256": "27255da19a036c3db65d132f41dc1d28980b84543f99724b5d1e8d529804eabe", "format": 1 }, "format": 1 diff --git a/ansible_collections/azure/azcollection/README.md b/ansible_collections/azure/azcollection/README.md index 69d9e7c0b..cdc2953a6 100644 --- a/ansible_collections/azure/azcollection/README.md +++ b/ansible_collections/azure/azcollection/README.md @@ -13,7 +13,7 @@ It is recommended to run ansible in [Virtualenv](https://virtualenv.pypa.io/en/l ## Requirements -- ansible version >= 2.9 +- ansible version >= 2.14 To install Azure collection hosted in Galaxy: diff --git a/ansible_collections/azure/azcollection/meta/runtime.yml b/ansible_collections/azure/azcollection/meta/runtime.yml index ccff76341..5870f6d89 100644 --- a/ansible_collections/azure/azcollection/meta/runtime.yml +++ b/ansible_collections/azure/azcollection/meta/runtime.yml @@ -1,5 +1,5 @@ --- -requires_ansible: '>=2.13.0' +requires_ansible: '>=2.14.0' action_groups: all: - azure.azcollection.azure_rm_account_info diff --git a/ansible_collections/azure/azcollection/plugins/doc_fragments/azure.py b/ansible_collections/azure/azcollection/plugins/doc_fragments/azure.py index bc382e401..74c1286ac 100644 --- a/ansible_collections/azure/azcollection/plugins/doc_fragments/azure.py +++ b/ansible_collections/azure/azcollection/plugins/doc_fragments/azure.py @@ -34,7 +34,8 @@ options: type: str client_id: description: - - Azure client ID. Use when authenticating with a Service Principal. + - Azure client ID. Use when authenticating with a Service Principal or Managed Identity (msi). + - Can also be set via the C(AZURE_CLIENT_ID) environment variable. type: str secret: description: @@ -65,6 +66,19 @@ options: type: str choices: [ ignore, validate ] version_added: '0.0.1' + disable_instance_discovery: + description: + - Determines whether or not instance discovery is performed when attempting to authenticate. + Setting this to true will completely disable both instance discovery and authority validation. + This functionality is intended for use in scenarios where the metadata endpoint cannot be reached + such as in private clouds or Azure Stack. The process of instance discovery entails retrieving + authority metadata from https://login.microsoft.com/ to validate the authority. By setting this + to **True**, the validation of the authority is disabled. As a result, it is crucial to ensure + that the configured authority host is valid and trustworthy. + - Set via credential file profile or the C(AZURE_DISABLE_INSTANCE_DISCOVERY) environment variable. + type: bool + default: False + version_added: '2.3.0' auth_source: description: - Controls the source of the credentials to use for authentication. diff --git a/ansible_collections/azure/azcollection/plugins/doc_fragments/azure_rm.py b/ansible_collections/azure/azcollection/plugins/doc_fragments/azure_rm.py index 8d860d863..6677137a1 100644 --- a/ansible_collections/azure/azcollection/plugins/doc_fragments/azure_rm.py +++ b/ansible_collections/azure/azcollection/plugins/doc_fragments/azure_rm.py @@ -47,6 +47,11 @@ options: expression in the list is evaluated for each host; when the expression is true, the host is excluded from the inventory. default: [] + include_host_filters: + description: Include hosts from the inventory with a list of Jinja2 conditional expressions. Each + expression in the list is evaluated for each host; when the expression is true, the host is included + in the inventory, all hosts are includes in the inventory by default. + default: [true] batch_fetch: description: To improve performance, results are fetched using an unsupported batch API. Disabling C(batch_fetch) uses a much slower serial fetch, resulting in many more round-trips. Generally only @@ -61,8 +66,8 @@ options: description: - By default this plugin is using a general group name sanitization to create safe and usable group names for use in Ansible. This option allows you to override that, in efforts to allow migration from the old inventory script and - matches the sanitization of groups when the script's ``replace_dash_in_groups`` option is set to ``False``. - To replicate behavior of ``replace_dash_in_groups = True`` with constructed groups, + matches the sanitization of groups when the script's C(replace_dash_in_groups) option is set to C(false). + To replicate behavior of C(replace_dash_in_groups = true) with constructed groups, you will need to replace hyphens with underscores via the regex_replace filter for those entries. - For this to work you should also turn off the TRANSFORM_INVALID_GROUP_CHARS setting, otherwise the core engine will just use the standard sanitization on top. @@ -86,9 +91,9 @@ options: - Ignores expression if result is an empty string or None value. - By default, inventory_hostname is generated to be globally unique based on the VM host name. See C(plain_host_names) for more details on the default. - - An expression of 'default' will force using the default hostname generator if no previous hostname expression + - An expression of C(default) will force using the default hostname generator if no previous hostname expression resulted in a valid hostname. - - Use ``default_inventory_hostname`` to access the default hostname generator's value in any of the Jinja2 expressions. + - Use C(default_inventory_hostname) to access the default hostname generator's value in any of the Jinja2 expressions. type: list elements: str default: [default] diff --git a/ansible_collections/azure/azcollection/plugins/inventory/azure_rm.py b/ansible_collections/azure/azcollection/plugins/inventory/azure_rm.py index 3442aa124..12970dec3 100644 --- a/ansible_collections/azure/azcollection/plugins/inventory/azure_rm.py +++ b/ansible_collections/azure/azcollection/plugins/inventory/azure_rm.py @@ -105,6 +105,14 @@ exclude_host_filters: - tags['tagkey2'] is defined and tags['tagkey2'] == 'tagkey2' # excludes hosts that are powered off - powerstate != 'running' + +# includes a host to the inventory when any of these expressions is true, can refer to any vars defined on the host +include_host_filters: + # includes hosts that in the eastus region and power on + - location in ['eastus'] and powerstate == 'running' + # includes hosts in the eastus region and power on OR includes hosts in the eastus2 region and tagkey is tagkey + - location in ['eastus'] and powerstate == 'running' + - location in ['eastus2'] and tags['tagkey'] is defined and tags['tagkey'] == 'tagkey' ''' # FUTURE: do we need a set of sane default filters, separate from the user-defineable ones? @@ -130,12 +138,15 @@ from ansible.errors import AnsibleParserError, AnsibleError from ansible.module_utils.parsing.convert_bool import boolean from ansible.module_utils._text import to_native, to_bytes, to_text from itertools import chain +from os import environ try: from azure.core._pipeline_client import PipelineClient from azure.core.pipeline.policies import BearerTokenCredentialPolicy from azure.core.configuration import Configuration from azure.mgmt.core.tools import parse_resource_id + from azure.core.pipeline import PipelineResponse + from azure.mgmt.core.polling.arm_polling import ARMPolling except ImportError: Configuration = object parse_resource_id = object @@ -199,7 +210,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable): if re.match(r'.{0,}azure_rm\.y(a)?ml$', path): return True # display.debug("azure_rm inventory filename must end with 'azure_rm.yml' or 'azure_rm.yaml'") - return False + raise AnsibleError("azure_rm inventory filename must end with 'azure_rm.yml' or 'azure_rm.yaml'") def parse(self, inventory, loader, path, cache=True): super(InventoryModule, self).parse(inventory, loader, path) @@ -215,6 +226,8 @@ class InventoryModule(BaseInventoryPlugin, Constructable): self._filters = self.get_option('exclude_host_filters') + self.get_option('default_host_filters') + self._include_filters = self.get_option('include_host_filters') + try: self._credential_setup() self._get_hosts() @@ -222,8 +235,9 @@ class InventoryModule(BaseInventoryPlugin, Constructable): raise def _credential_setup(self): + auth_source = environ.get('ANSIBLE_AZURE_AUTH_SOURCE', None) or self.get_option('auth_source') auth_options = dict( - auth_source=self.get_option('auth_source'), + auth_source=auth_source, profile=self.get_option('profile'), subscription_id=self.get_option('subscription_id'), client_id=self.get_option('client_id'), @@ -238,6 +252,18 @@ class InventoryModule(BaseInventoryPlugin, Constructable): adfs_authority_url=self.get_option('adfs_authority_url') ) + if self.templar.is_template(auth_options["tenant"]): + auth_options["tenant"] = self.templar.template(variable=auth_options["tenant"], disable_lookups=False) + + if self.templar.is_template(auth_options["client_id"]): + auth_options["client_id"] = self.templar.template(variable=auth_options["client_id"], disable_lookups=False) + + if self.templar.is_template(auth_options["secret"]): + auth_options["secret"] = self.templar.template(variable=auth_options["secret"], disable_lookups=False) + + if self.templar.is_template(auth_options["subscription_id"]): + auth_options["subscription_id"] = self.templar.template(variable=auth_options["subscription_id"], disable_lookups=False) + self.azure_auth = AzureRMAuth(**auth_options) self._clientconfig = AzureRMRestConfiguration(self.azure_auth.azure_credential_track2, self.azure_auth.subscription_id, @@ -297,12 +323,14 @@ class InventoryModule(BaseInventoryPlugin, Constructable): for h in self._hosts: # FUTURE: track hostnames to warn if a hostname is repeated (can happen for legacy and for composed inventory_hostname) inventory_hostname = self._get_hostname(h, hostnames=constructable_hostnames, strict=constructable_config_strict) - if self._filter_host(inventory_hostname, h.hostvars): + if self._filter_exclude_host(inventory_hostname, h.hostvars): + continue + if not self._filter_include_host(inventory_hostname, h.hostvars): continue self.inventory.add_host(inventory_hostname) # FUTURE: configurable default IP list? can already do this via hostvar_expressions self.inventory.set_variable(inventory_hostname, "ansible_host", - next(chain(h.hostvars['public_ipv4_addresses'], h.hostvars['private_ipv4_addresses']), None)) + next(chain(h.hostvars['public_ipv4_address'], h.hostvars['private_ipv4_addresses']), None)) for k, v in iteritems(h.hostvars): # FUTURE: configurable hostvar prefix? Makes docs harder... self.inventory.set_variable(inventory_hostname, k, v) @@ -313,10 +341,10 @@ class InventoryModule(BaseInventoryPlugin, Constructable): self._add_host_to_keyed_groups(constructable_config_keyed_groups, h.hostvars, inventory_hostname, strict=constructable_config_strict) # FUTURE: fix underlying inventory stuff to allow us to quickly access known groupvars from reconciled host - def _filter_host(self, inventory_hostname, hostvars): + def _filter_host(self, filter, inventory_hostname, hostvars): self.templar.available_variables = hostvars - for condition in self._filters: + for condition in filter: # FUTURE: should warn/fail if conditional doesn't return True or False conditional = "{{% if {0} %}} True {{% else %}} False {{% endif %}}".format(condition) try: @@ -329,6 +357,12 @@ class InventoryModule(BaseInventoryPlugin, Constructable): return False + def _filter_include_host(self, inventory_hostname, hostvars): + return self._filter_host(self._include_filters, inventory_hostname, hostvars) + + def _filter_exclude_host(self, inventory_hostname, hostvars): + return self._filter_host(self._filters, inventory_hostname, hostvars) + def _get_hostname(self, host, hostnames=None, strict=False): hostname = None errors = [] @@ -441,8 +475,18 @@ class InventoryModule(BaseInventoryPlugin, Constructable): request_new = self.new_client.post(url, query_parameters, header_parameters, body_content) response = self.new_client.send_request(request_new) - - return json.loads(response.body()) + if response.status_code == 202: + try: + poller = ARMPolling(timeout=3) + poller.initialize(client=self.new_client, + initial_response=PipelineResponse(None, response, None), + deserialization_callback=lambda r: r) + poller.run() + return poller.resource().context['deserialized_data'] + except Exception as ec: + raise + else: + return json.loads(response.body()) def send_request(self, url, api_version): query_parameters = {'api-version': api_version} @@ -525,9 +569,11 @@ class AzureHost(object): network_interface_id=[], security_group_id=[], security_group=[], - public_ipv4_addresses=[], + public_ip_address=[], + public_ipv4_address=[], public_dns_hostnames=[], private_ipv4_addresses=[], + subnet=[], id=self._vm_model['id'], location=self._vm_model['location'], name=self._vm_model['name'], @@ -550,25 +596,34 @@ class AzureHost(object): resource_group=parse_resource_id(self._vm_model['id']).get('resource_group').lower(), default_inventory_hostname=self.default_inventory_hostname, creation_time=self._vm_model['properties']['timeCreated'], + license_type=self._vm_model['properties'].get('licenseType', 'Unknown') ) # set nic-related values from the primary NIC first for nic in sorted(self.nics, key=lambda n: n.is_primary, reverse=True): # and from the primary IP config per NIC first for ipc in sorted(nic._nic_model['properties']['ipConfigurations'], key=lambda i: i['properties'].get('primary', False), reverse=True): - private_ip = ipc['properties'].get('privateIPAddress') - if private_ip: - new_hostvars['private_ipv4_addresses'].append(private_ip) - pip_id = ipc['properties'].get('publicIPAddress', {}).get('id') - if pip_id: - new_hostvars['public_ip_id'] = pip_id - - pip = nic.public_ips[pip_id] - new_hostvars['public_ip_name'] = pip._pip_model['name'] - new_hostvars['public_ipv4_addresses'].append(pip._pip_model['properties'].get('ipAddress', None)) - pip_fqdn = pip._pip_model['properties'].get('dnsSettings', {}).get('fqdn') - if pip_fqdn: - new_hostvars['public_dns_hostnames'].append(pip_fqdn) + try: + subnet = ipc['properties'].get('subnet') + if subnet: + new_hostvars['subnet'].append(subnet) + private_ip = ipc['properties'].get('privateIPAddress') + if private_ip: + new_hostvars['private_ipv4_addresses'].append(private_ip) + pip_id = ipc['properties'].get('publicIPAddress', {}).get('id') + if pip_id and pip_id in nic.public_ips: + pip = nic.public_ips[pip_id] + new_hostvars['public_ipv4_address'].append(pip._pip_model['properties'].get('ipAddress', None)) + new_hostvars['public_ip_address'].append({ + 'id': pip_id, + 'name': pip._pip_model['name'], + 'ipv4_address': pip._pip_model['properties'].get('ipAddress', None), + }) + pip_fqdn = pip._pip_model['properties'].get('dnsSettings', {}).get('fqdn') + if pip_fqdn: + new_hostvars['public_dns_hostnames'].append(pip_fqdn) + except Exception: + continue new_hostvars['mac_address'].append(nic._nic_model['properties'].get('macAddress')) new_hostvars['network_interface'].append(nic._nic_model['name']) diff --git a/ansible_collections/azure/azcollection/plugins/lookup/azure_keyvault_secret.py b/ansible_collections/azure/azcollection/plugins/lookup/azure_keyvault_secret.py index ea2183a5a..5e693e4b3 100644 --- a/ansible_collections/azure/azcollection/plugins/lookup/azure_keyvault_secret.py +++ b/ansible_collections/azure/azcollection/plugins/lookup/azure_keyvault_secret.py @@ -32,6 +32,8 @@ options: description: Secret of the service principal. tenant_id: description: Tenant id of service principal. + use_msi: + description: MSI token autodiscover, default is true. notes: - If version is not provided, this plugin will return the latest version of the secret. - If ansible is running on Azure Virtual Machine with MSI enabled, client_id, secret and tenant isn't required. @@ -74,7 +76,8 @@ EXAMPLE = """ vault_url=url, client_id=client_id, secret=secret, - tenant_id=tenant + tenant_id=tenant, + use_msi=false ) }}" @@ -139,22 +142,6 @@ token_headers = { 'Metadata': 'true' } -token = None - -try: - token_res = requests.get('http://169.254.169.254/metadata/identity/oauth2/token', params=token_params, headers=token_headers, timeout=(3.05, 27)) - if token_res.ok: - token = token_res.json().get("access_token") - if token is not None: - TOKEN_ACQUIRED = True - else: - display.v('Successfully called MSI endpoint, but no token was available. Will use service principal if provided.') - else: - display.v("Unable to query MSI endpoint, Error Code %s. Will use service principal if provided" % token_res.status_code) -except Exception: - display.v('Unable to fetch MSI token. Will use service principal if provided.') - TOKEN_ACQUIRED = False - def lookup_secret_non_msi(terms, vault_url, kwargs): @@ -187,6 +174,27 @@ class LookupModule(LookupBase): def run(self, terms, variables, **kwargs): ret = [] vault_url = kwargs.pop('vault_url', None) + use_msi = kwargs.pop('use_msi', True) + TOKEN_ACQUIRED = False + token = None + + if use_msi: + try: + token_res = requests.get('http://169.254.169.254/metadata/identity/oauth2/token', + params=token_params, + headers=token_headers, + timeout=(3.05, 27)) + if token_res.ok: + token = token_res.json().get("access_token") + if token is not None: + TOKEN_ACQUIRED = True + else: + display.v('Successfully called MSI endpoint, but no token was available. Will use service principal if provided.') + else: + display.v("Unable to query MSI endpoint, Error Code %s. Will use service principal if provided" % token_res.status_code) + except Exception: + display.v('Unable to fetch MSI token. Will use service principal if provided.') + if vault_url is None: raise AnsibleError('Failed to get valid vault url.') if TOKEN_ACQUIRED: diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultsecret/lookup_plugins/azure_service_principal_attribute.py b/ansible_collections/azure/azcollection/plugins/lookup/azure_service_principal_attribute.py index c6f488f13..1b1941026 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultsecret/lookup_plugins/azure_service_principal_attribute.py +++ b/ansible_collections/azure/azcollection/plugins/lookup/azure_service_principal_attribute.py @@ -5,15 +5,16 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type DOCUMENTATION = """ -lookup: azure_service_principal_attribute +--- +name: azure_service_principal_attribute requirements: - - azure-graphrbac + - msgraph-sdk author: - - Yunge Zhu <yungez@microsoft.com> + - Yunge Zhu (@yungezz) -version_added: "2.7" +version_added: "1.12.0" short_description: Look up Azure service principal attributes. @@ -49,12 +50,13 @@ from ansible.plugins.lookup import LookupBase from ansible.module_utils._text import to_native try: - from azure.common.credentials import ServicePrincipalCredentials - from azure.graphrbac import GraphRbacManagementClient from azure.cli.core import cloud as azure_cloud + from azure.identity._credentials.client_secret import ClientSecretCredential + import asyncio + from msgraph import GraphServiceClient + from msgraph.generated.service_principals.service_principals_request_builder import ServicePrincipalsRequestBuilder except ImportError: - raise AnsibleError( - "The lookup azure_service_principal_attribute requires azure.graphrbac, msrest") + pass class LookupModule(LookupBase): @@ -72,21 +74,28 @@ class LookupModule(LookupBase): _cloud_environment = azure_cloud.AZURE_PUBLIC_CLOUD if self.get_option('azure_cloud_environment', None) is not None: - cloud_environment = azure_cloud.get_cloud_from_metadata_endpoint(credentials['azure_cloud_environment']) + _cloud_environment = azure_cloud.get_cloud_from_metadata_endpoint(credentials['azure_cloud_environment']) try: - azure_credentials = ServicePrincipalCredentials(client_id=credentials['azure_client_id'], - secret=credentials['azure_secret'], - tenant=credentials['azure_tenant'], - resource=_cloud_environment.endpoints.active_directory_graph_resource_id) + azure_credential_track2 = ClientSecretCredential(client_id=credentials['azure_client_id'], + client_secret=credentials['azure_secret'], + tenant_id=credentials['azure_tenant'], + authority=_cloud_environment.endpoints.active_directory) - client = GraphRbacManagementClient(azure_credentials, credentials['azure_tenant'], - base_url=_cloud_environment.endpoints.active_directory_graph_resource_id) + client = GraphServiceClient(azure_credential_track2) - response = list(client.service_principals.list(filter="appId eq '{0}'".format(credentials['azure_client_id']))) - sp = response[0] - - return sp.object_id.split(',') + response = asyncio.get_event_loop().run_until_complete(self.get_service_principals(client, credentials['azure_client_id'])) + if not response: + return [] + return list(response.value)[0].id.split(',') except Exception as ex: raise AnsibleError("Failed to get service principal object id: %s" % to_native(ex)) return False + + async def get_service_principals(self, _client, app_id): + request_configuration = ServicePrincipalsRequestBuilder.ServicePrincipalsRequestBuilderGetRequestConfiguration( + query_parameters=ServicePrincipalsRequestBuilder.ServicePrincipalsRequestBuilderGetQueryParameters( + filter="servicePrincipalNames/any(c:c eq '{0}')".format(app_id), + ) + ) + return await _client.service_principals.get(request_configuration=request_configuration) diff --git a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common.py b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common.py index 9c0e6e839..79b5167b1 100644 --- a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common.py +++ b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common.py @@ -15,10 +15,6 @@ import inspect import traceback import json -try: - from azure.graphrbac import GraphRbacManagementClient -except Exception: - pass from os.path import expanduser from ansible.module_utils.basic import \ @@ -53,6 +49,7 @@ AZURE_COMMON_ARGS = dict( log_path=dict(type='str', no_log=True), x509_certificate_path=dict(type='path', no_log=True), thumbprint=dict(type='str', no_log=True), + disable_instance_discovery=dict(type='bool', default=False), ) AZURE_CREDENTIAL_ENV_MAPPING = dict( @@ -67,7 +64,8 @@ AZURE_CREDENTIAL_ENV_MAPPING = dict( cert_validation_mode='AZURE_CERT_VALIDATION_MODE', adfs_authority_url='AZURE_ADFS_AUTHORITY_URL', x509_certificate_path='AZURE_X509_CERTIFICATE_PATH', - thumbprint='AZURE_THUMBPRINT' + thumbprint='AZURE_THUMBPRINT', + disable_instance_discovery='AZURE_DISABLE_INSTANCE_DISCOVERY' ) @@ -114,7 +112,28 @@ AZURE_API_PROFILES = { 'ManagementLockClient': '2016-09-01', 'DataLakeStoreAccountManagementClient': '2016-11-01', 'NotificationHubsManagementClient': '2016-03-01', - 'EventHubManagementClient': '2018-05-04' + 'EventHubManagementClient': '2021-11-01', + 'GenericRestClient': 'latest', + 'DnsManagementClient': '2018-05-01', + 'PrivateDnsManagementClient': 'latest', + 'ContainerServiceClient': '2022-02-01', + 'SqlManagementClient': 'latest', + 'ContainerRegistryManagementClient': '2021-09-01', + 'MarketplaceOrderingAgreements': 'latest', + 'TrafficManagerManagementClient': 'latest', + 'MonitorManagementClient': '2016-03-01', + 'LogAnalyticsManagementClient': 'latest', + 'ServiceBusManagementClient': 'latest', + 'AutomationClient': 'latest', + 'IotHubClient': 'latest', + 'RecoveryServicesBackupClient': 'latest', + 'DataFactoryManagementClient': 'latest', + 'KeyVaultManagementClient': '2021-10-01', + 'HDInsightManagementClient': 'latest', + 'DevTestLabsClient': 'latest', + 'CosmosDBManagementClient': 'latest', + 'CdnManagementClient': '2017-04-02', + 'BatchManagementClient': 'latest', }, '2019-03-01-hybrid': { 'StorageManagementClient': '2017-10-01', @@ -220,11 +239,8 @@ except ImportError: try: from enum import Enum - from msrestazure.azure_active_directory import AADTokenCredentials - from msrestazure.azure_active_directory import MSIAuthentication from azure.mgmt.core.tools import parse_resource_id, resource_id, is_valid_resource_id from azure.cli.core import cloud as azure_cloud - from azure.common.credentials import ServicePrincipalCredentials, UserPassCredentials from azure.mgmt.network import NetworkManagementClient from azure.mgmt.resource.resources import ResourceManagementClient from azure.mgmt.managementgroups import ManagementGroupsAPI as ManagementGroupsClient @@ -240,11 +256,11 @@ try: from azure.mgmt.marketplaceordering import MarketplaceOrderingAgreements from azure.mgmt.trafficmanager import TrafficManagerManagementClient from azure.storage.blob import BlobServiceClient - from msal.application import ClientApplication, ConfidentialClientApplication from azure.mgmt.authorization import AuthorizationManagementClient from azure.mgmt.sql import SqlManagementClient from azure.mgmt.servicebus import ServiceBusManagementClient from azure.mgmt.rdbms.postgresql import PostgreSQLManagementClient + from azure.mgmt.rdbms.postgresql_flexibleservers import PostgreSQLManagementClient as PostgreSQLFlexibleManagementClient from azure.mgmt.rdbms.mysql import MySQLManagementClient from azure.mgmt.rdbms.mariadb import MariaDBManagementClient from azure.mgmt.containerregistry import ContainerRegistryManagementClient @@ -257,7 +273,11 @@ try: from azure.mgmt.iothub import models as IoTHubModels from azure.mgmt.resource.locks import ManagementLockClient from azure.mgmt.recoveryservicesbackup import RecoveryServicesBackupClient - import azure.mgmt.recoveryservicesbackup.models as RecoveryServicesBackupModels + try: + # Older versions of the library exposed the modules at the root of the package + import azure.mgmt.recoveryservicesbackup.models as RecoveryServicesBackupModels + except ImportError: + import azure.mgmt.recoveryservicesbackup.activestamp.models as RecoveryServicesBackupModels from azure.mgmt.search import SearchManagementClient from azure.mgmt.datalake.store import DataLakeStoreAccountManagementClient import azure.mgmt.datalake.store.models as DataLakeStoreAccountModel @@ -266,6 +286,8 @@ try: from azure.mgmt.datafactory import DataFactoryManagementClient import azure.mgmt.datafactory.models as DataFactoryModel from azure.identity._credentials import client_secret, user_password, certificate, managed_identity + from azure.identity import AzureCliCredential + from msgraph import GraphServiceClient except ImportError as exc: Authentication = object @@ -415,6 +437,7 @@ class AzureRMModuleBase(object): self._mysql_client = None self._mariadb_client = None self._postgresql_client = None + self._postgresql_flexible_client = None self._containerregistry_client = None self._containerinstance_client = None self._containerservice_client = None @@ -484,8 +507,8 @@ class AzureRMModuleBase(object): ''' self.module.fail_json(msg=msg, **kwargs) - def deprecate(self, msg, version=None): - self.module.deprecate(msg, version) + def deprecate(self, msg, version=None, collection_name='azure.azcollection'): + self.module.deprecate(msg, version, collection_name=collection_name) def log(self, msg, pretty_print=False): if pretty_print: @@ -675,11 +698,15 @@ class AzureRMModuleBase(object): self.fail("Error {0} has a provisioning state of {1}. Expecting state to be {2}.".format( azure_object.name, azure_object.provisioning_state, AZURE_SUCCESS_STATE)) - def get_blob_service_client(self, resource_group_name, storage_account_name): + def get_blob_service_client(self, resource_group_name, storage_account_name, auth_mode='key'): try: self.log("Getting storage account detail") account = self.storage_client.storage_accounts.get_properties(resource_group_name=resource_group_name, account_name=storage_account_name) - account_keys = self.storage_client.storage_accounts.list_keys(resource_group_name=resource_group_name, account_name=storage_account_name) + if auth_mode == 'login' and self.azure_auth.credentials.get('credential'): + credential = self.azure_auth.credentials['credential'] + else: + account_keys = self.storage_client.storage_accounts.list_keys(resource_group_name=resource_group_name, account_name=storage_account_name) + credential = account_keys.keys[0].value except Exception as exc: self.fail("Error getting storage account detail for {0}: {1}".format(storage_account_name, str(exc))) @@ -687,7 +714,7 @@ class AzureRMModuleBase(object): self.log("Create blob service client") return BlobServiceClient( account_url=account.primary_endpoints.blob, - credential=account_keys.keys[0].value, + credential=credential, ) except Exception as exc: self.fail("Error creating blob service client for storage account {0} - {1}".format(storage_account_name, str(exc))) @@ -854,14 +881,17 @@ class AzureRMModuleBase(object): # wrap basic strings in a dict that just defines the default return dict(default_api_version=profile_raw) - def get_graphrbac_client(self, tenant_id): - cred = self.azure_auth.azure_credentials - base_url = self.azure_auth._cloud_environment.endpoints.active_directory_graph_resource_id - client = GraphRbacManagementClient(cred, tenant_id, base_url) + # The graphrbac has deprecated, migrate to msgraph + # def get_graphrbac_client(self, tenant_id): + # cred = self.azure_auth.azure_credentials + # base_url = self.azure_auth._cloud_environment.endpoints.active_directory_graph_resource_id + # client = GraphRbacManagementClient(cred, tenant_id, base_url) + # return client - return client + def get_msgraph_client(self): + return GraphServiceClient(self.azure_auth.azure_credential_track2) - def get_mgmt_svc_client(self, client_type, base_url=None, api_version=None, suppress_subscription_id=False, is_track2=False): + def get_mgmt_svc_client(self, client_type, base_url=None, api_version=None, suppress_subscription_id=False): self.log('Getting management service client {0}'.format(client_type.__name__)) self.check_client_version(client_type) @@ -883,16 +913,10 @@ class AzureRMModuleBase(object): # Some management clients do not take a subscription ID as parameters. if suppress_subscription_id: - if is_track2: - client_kwargs = dict(credential=self.azure_auth.azure_credential_track2, base_url=base_url, credential_scopes=[base_url + ".default"]) - else: - client_kwargs = dict(credentials=self.azure_auth.azure_credentials, base_url=base_url) + client_kwargs = dict(credential=self.azure_auth.azure_credential_track2, base_url=base_url, credential_scopes=[base_url + ".default"]) else: - if is_track2: - client_kwargs = dict(credential=self.azure_auth.azure_credential_track2, - subscription_id=mgmt_subscription_id, base_url=base_url, credential_scopes=[base_url + ".default"]) - else: - client_kwargs = dict(credentials=self.azure_auth.azure_credentials, subscription_id=mgmt_subscription_id, base_url=base_url) + client_kwargs = dict(credential=self.azure_auth.azure_credential_track2, + subscription_id=mgmt_subscription_id, base_url=base_url, credential_scopes=[base_url + ".default"]) api_profile_dict = {} @@ -926,13 +950,8 @@ class AzureRMModuleBase(object): setattr(client, '_ansible_models', importlib.import_module(client_type.__module__).models) client.models = types.MethodType(_ansible_get_models, client) - if not is_track2: - client.config = self.add_user_agent(client.config) - if self.azure_auth._cert_validation_mode == 'ignore': - client.config.session_configuration_callback = self._validation_ignore_callback - else: - if self.azure_auth._cert_validation_mode == 'ignore': - client._config.session_configuration_callback = self._validation_ignore_callback + if self.azure_auth._cert_validation_mode == 'ignore': + client._config.session_configuration_callback = self._validation_ignore_callback return client @@ -992,7 +1011,6 @@ class AzureRMModuleBase(object): if not self._storage_client: self._storage_client = self.get_mgmt_svc_client(StorageManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2021-06-01') return self._storage_client @@ -1006,7 +1024,6 @@ class AzureRMModuleBase(object): if not self._authorization_client: self._authorization_client = self.get_mgmt_svc_client(AuthorizationManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2020-04-01-preview') return self._authorization_client @@ -1021,7 +1038,6 @@ class AzureRMModuleBase(object): self._subscription_client = self.get_mgmt_svc_client(SubscriptionClient, base_url=self._cloud_environment.endpoints.resource_manager, suppress_subscription_id=True, - is_track2=True, api_version='2019-11-01') return self._subscription_client @@ -1036,7 +1052,6 @@ class AzureRMModuleBase(object): self._management_group_client = self.get_mgmt_svc_client(ManagementGroupsClient, base_url=self._cloud_environment.endpoints.resource_manager, suppress_subscription_id=True, - is_track2=True, api_version='2020-05-01') return self._management_group_client @@ -1046,7 +1061,6 @@ class AzureRMModuleBase(object): if not self._network_client: self._network_client = self.get_mgmt_svc_client(NetworkManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2021-03-01') return self._network_client @@ -1061,7 +1075,6 @@ class AzureRMModuleBase(object): if not self._resource_client: self._resource_client = self.get_mgmt_svc_client(ResourceManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2019-10-01') return self._resource_client @@ -1076,7 +1089,6 @@ class AzureRMModuleBase(object): if not self._image_client: self._image_client = self.get_mgmt_svc_client(ComputeManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2021-04-01') return self._image_client @@ -1091,7 +1103,6 @@ class AzureRMModuleBase(object): if not self._compute_client: self._compute_client = self.get_mgmt_svc_client(ComputeManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2021-04-01') return self._compute_client @@ -1106,7 +1117,6 @@ class AzureRMModuleBase(object): if not self._dns_client: self._dns_client = self.get_mgmt_svc_client(DnsManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2018-05-01') return self._dns_client @@ -1121,7 +1131,6 @@ class AzureRMModuleBase(object): if not self._private_dns_client: self._private_dns_client = self.get_mgmt_svc_client( PrivateDnsManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) return self._private_dns_client @@ -1136,7 +1145,6 @@ class AzureRMModuleBase(object): if not self._web_client: self._web_client = self.get_mgmt_svc_client(WebSiteManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2021-03-01') return self._web_client @@ -1146,7 +1154,6 @@ class AzureRMModuleBase(object): if not self._containerservice_client: self._containerservice_client = self.get_mgmt_svc_client(ContainerServiceClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2017-07-01') return self._containerservice_client @@ -1161,7 +1168,6 @@ class AzureRMModuleBase(object): if not self._managedcluster_client: self._managedcluster_client = self.get_mgmt_svc_client(ContainerServiceClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2022-02-01') return self._managedcluster_client @@ -1170,16 +1176,22 @@ class AzureRMModuleBase(object): self.log('Getting SQL client') if not self._sql_client: self._sql_client = self.get_mgmt_svc_client(SqlManagementClient, - base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True) + base_url=self._cloud_environment.endpoints.resource_manager) return self._sql_client @property + def postgresql_flexible_client(self): + self.log('Getting PostgreSQL client') + if not self._postgresql_flexible_client: + self._postgresql_flexible_client = self.get_mgmt_svc_client(PostgreSQLFlexibleManagementClient, + base_url=self._cloud_environment.endpoints.resource_manager) + return self._postgresql_flexible_client + + @property def postgresql_client(self): self.log('Getting PostgreSQL client') if not self._postgresql_client: self._postgresql_client = self.get_mgmt_svc_client(PostgreSQLManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) return self._postgresql_client @@ -1188,7 +1200,6 @@ class AzureRMModuleBase(object): self.log('Getting MySQL client') if not self._mysql_client: self._mysql_client = self.get_mgmt_svc_client(MySQLManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) return self._mysql_client @@ -1197,7 +1208,6 @@ class AzureRMModuleBase(object): self.log('Getting MariaDB client') if not self._mariadb_client: self._mariadb_client = self.get_mgmt_svc_client(MariaDBManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) return self._mariadb_client @@ -1207,7 +1217,6 @@ class AzureRMModuleBase(object): if not self._containerregistry_client: self._containerregistry_client = self.get_mgmt_svc_client(ContainerRegistryManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2021-09-01') return self._containerregistry_client @@ -1218,7 +1227,6 @@ class AzureRMModuleBase(object): if not self._containerinstance_client: self._containerinstance_client = self.get_mgmt_svc_client(ContainerInstanceManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2018-06-01') return self._containerinstance_client @@ -1228,7 +1236,6 @@ class AzureRMModuleBase(object): self.log('Getting marketplace agreement client') if not self._marketplace_client: self._marketplace_client = self.get_mgmt_svc_client(MarketplaceOrderingAgreements, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) return self._marketplace_client @@ -1237,7 +1244,6 @@ class AzureRMModuleBase(object): self.log('Getting traffic manager client') if not self._traffic_manager_management_client: self._traffic_manager_management_client = self.get_mgmt_svc_client(TrafficManagerManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) return self._traffic_manager_management_client @@ -1247,8 +1253,7 @@ class AzureRMModuleBase(object): if not self._monitor_autoscale_settings_client: self._monitor_autoscale_settings_client = self.get_mgmt_svc_client(MonitorManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - api_version="2015-04-01", - is_track2=True) + api_version="2015-04-01") return self._monitor_autoscale_settings_client @property @@ -1257,8 +1262,7 @@ class AzureRMModuleBase(object): if not self._monitor_log_profiles_client: self._monitor_log_profiles_client = self.get_mgmt_svc_client(MonitorManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - api_version="2016-03-01", - is_track2=True) + api_version="2016-03-01") return self._monitor_log_profiles_client @property @@ -1267,8 +1271,7 @@ class AzureRMModuleBase(object): if not self._monitor_diagnostic_settings_client: self._monitor_diagnostic_settings_client = self.get_mgmt_svc_client(MonitorManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - api_version="2021-05-01-preview", - is_track2=True) + api_version="2021-05-01-preview") return self._monitor_diagnostic_settings_client @property @@ -1276,7 +1279,6 @@ class AzureRMModuleBase(object): self.log('Getting log analytics client') if not self._log_analytics_client: self._log_analytics_client = self.get_mgmt_svc_client(LogAnalyticsManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) return self._log_analytics_client @@ -1290,7 +1292,6 @@ class AzureRMModuleBase(object): self.log('Getting servicebus client') if not self._servicebus_client: self._servicebus_client = self.get_mgmt_svc_client(ServiceBusManagementClient, - is_track2=True, api_version="2021-06-01-preview", base_url=self._cloud_environment.endpoints.resource_manager) return self._servicebus_client @@ -1304,8 +1305,7 @@ class AzureRMModuleBase(object): self.log('Getting automation client') if not self._automation_client: self._automation_client = self.get_mgmt_svc_client(AutomationClient, - base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True) + base_url=self._cloud_environment.endpoints.resource_manager) return self._automation_client @property @@ -1317,7 +1317,6 @@ class AzureRMModuleBase(object): self.log('Getting iothub client') if not self._IoThub_client: self._IoThub_client = self.get_mgmt_svc_client(IotHubClient, - is_track2=True, api_version='2018-04-01', base_url=self._cloud_environment.endpoints.resource_manager) return self._IoThub_client @@ -1332,7 +1331,6 @@ class AzureRMModuleBase(object): if not self._lock_client: self._lock_client = self.get_mgmt_svc_client(ManagementLockClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2016-09-01') return self._lock_client @@ -1346,7 +1344,6 @@ class AzureRMModuleBase(object): self.log('Getting recovery services backup client') if not self._recovery_services_backup_client: self._recovery_services_backup_client = self.get_mgmt_svc_client(RecoveryServicesBackupClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) return self._recovery_services_backup_client @@ -1360,7 +1357,6 @@ class AzureRMModuleBase(object): if not self._search_client: self._search_client = self.get_mgmt_svc_client(SearchManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2020-08-01') return self._search_client @@ -1370,7 +1366,6 @@ class AzureRMModuleBase(object): if not self._datalake_store_client: self._datalake_store_client = self.get_mgmt_svc_client(DataLakeStoreAccountManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2016-11-01') return self._datalake_store_client @@ -1385,7 +1380,6 @@ class AzureRMModuleBase(object): self._notification_hub_client = self.get_mgmt_svc_client( NotificationHubsManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2016-03-01') return self._notification_hub_client @@ -1396,7 +1390,6 @@ class AzureRMModuleBase(object): self._event_hub_client = self.get_mgmt_svc_client( EventHubManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2021-11-01') return self._event_hub_client @@ -1405,7 +1398,6 @@ class AzureRMModuleBase(object): self.log('Getting datafactory client...') if not self._datafactory_client: self._datafactory_client = self.get_mgmt_svc_client(DataFactoryManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) return self._datafactory_client @@ -1425,7 +1417,8 @@ class AzureRMAuth(object): def __init__(self, auth_source=None, profile=None, subscription_id=None, client_id=None, secret=None, tenant=None, ad_user=None, password=None, cloud_environment='AzureCloud', cert_validation_mode='validate', api_profile='latest', adfs_authority_url=None, fail_impl=None, is_ad_resource=False, - x509_certificate_path=None, thumbprint=None, track1_cred=False, **kwargs): + x509_certificate_path=None, thumbprint=None, track1_cred=False, + disable_instance_discovery=False, **kwargs): if fail_impl: self._fail_impl = fail_impl @@ -1448,7 +1441,8 @@ class AzureRMAuth(object): api_profile=api_profile, adfs_authority_url=adfs_authority_url, x509_certificate_path=x509_certificate_path, - thumbprint=thumbprint) + thumbprint=thumbprint, + disable_instance_discovery=disable_instance_discovery) if not self.credentials: if HAS_AZURE_CLI_CORE: @@ -1467,6 +1461,12 @@ class AzureRMAuth(object): if self._cert_validation_mode not in ['validate', 'ignore']: self.fail('invalid cert_validation_mode: {0}'.format(self._cert_validation_mode)) + # Disable instance discovery: module-arg, credential profile, env, "False" + self._disable_instance_discovery = disable_instance_discovery or \ + self.credentials.get('disable_instance_discovery') or \ + self._get_env('disable_instance_discovery') or \ + False + # if cloud_environment specified, look up/build Cloud object raw_cloud_env = self.credentials.get('cloud_environment') if self.credentials.get('credentials') is not None and raw_cloud_env is not None: @@ -1504,84 +1504,50 @@ class AzureRMAuth(object): if self.credentials.get('auth_source') == 'msi': # MSI Credentials - if is_ad_resource or track1_cred: - self.azure_credentials = self.credentials['credentials'] - self.azure_credential_track2 = self.credentials['credential'] + self.azure_credential_track2 = self.credentials['credentials'] elif self.credentials.get('credentials') is not None: # AzureCLI credentials - if is_ad_resource or track1_cred: - self.azure_credentials = self.credentials['credentials'] self.azure_credential_track2 = self.credentials['credentials'] elif self.credentials.get('client_id') is not None and \ self.credentials.get('secret') is not None and \ self.credentials.get('tenant') is not None: - - graph_resource = self._cloud_environment.endpoints.active_directory_graph_resource_id - rm_resource = self._cloud_environment.endpoints.resource_manager - if is_ad_resource or track1_cred: - self.azure_credentials = ServicePrincipalCredentials(client_id=self.credentials['client_id'], - secret=self.credentials['secret'], - tenant=self.credentials['tenant'], - cloud_environment=self._cloud_environment, - resource=graph_resource if self.is_ad_resource else rm_resource, - verify=self._cert_validation_mode == 'validate') self.azure_credential_track2 = client_secret.ClientSecretCredential(client_id=self.credentials['client_id'], client_secret=self.credentials['secret'], tenant_id=self.credentials['tenant'], - authority=self._adfs_authority_url) + authority=self._adfs_authority_url, + disable_instance_discovery=self._disable_instance_discovery) elif self.credentials.get('client_id') is not None and \ self.credentials.get('tenant') is not None and \ self.credentials.get('thumbprint') is not None and \ self.credentials.get('x509_certificate_path') is not None: - if is_ad_resource or track1_cred: - self.azure_credentials = self.acquire_token_with_client_certificate( - self._adfs_authority_url, - self.credentials['x509_certificate_path'], - self.credentials['thumbprint'], - self.credentials['client_id'], - self.credentials['tenant']) - self.azure_credential_track2 = certificate.CertificateCredential(tenant_id=self.credentials['tenant'], client_id=self.credentials['client_id'], certificate_path=self.credentials['x509_certificate_path'], - authority=self._adfs_authority_url) + authority=self._adfs_authority_url, + disable_instance_discovery=self._disable_instance_discovery) elif self.credentials.get('ad_user') is not None and \ self.credentials.get('password') is not None and \ self.credentials.get('client_id') is not None and \ self.credentials.get('tenant') is not None: - if is_ad_resource or track1_cred: - self.azure_credentials = self.acquire_token_with_username_password( - self._adfs_authority_url, - self.credentials['ad_user'], - self.credentials['password'], - self.credentials['client_id'], - self.credentials['tenant']) self.azure_credential_track2 = user_password.UsernamePasswordCredential(username=self.credentials['ad_user'], password=self.credentials['password'], tenant_id=self.credentials.get('tenant'), client_id=self.credentials.get('client_id'), - authority=self._adfs_authority_url) + authority=self._adfs_authority_url, + disable_instance_discovery=self._disable_instance_discovery) elif self.credentials.get('ad_user') is not None and self.credentials.get('password') is not None: - tenant = self.credentials.get('tenant') - if not tenant: - tenant = 'common' # SDK default - - if is_ad_resource or track1_cred: - self.azure_credentials = UserPassCredentials(self.credentials['ad_user'], - self.credentials['password'], - tenant=tenant, - cloud_environment=self._cloud_environment, - verify=self._cert_validation_mode == 'validate') - - client_id = self.credentials.get('client_id', '04b07795-8ddb-461a-bbee-02f9e1bf7b46') + client_id = self.credentials.get('client_id') + if client_id is None: + client_id = '04b07795-8ddb-461a-bbee-02f9e1bf7b46' self.azure_credential_track2 = user_password.UsernamePasswordCredential(username=self.credentials['ad_user'], password=self.credentials['password'], tenant_id=self.credentials.get('tenant', 'organizations'), client_id=client_id, - authority=self._adfs_authority_url) + authority=self._adfs_authority_url, + disable_instance_discovery=self._disable_instance_discovery) else: self.fail("Failed to authenticate with provided credentials. Some attributes were missing. " @@ -1640,7 +1606,7 @@ class AzureRMAuth(object): except Exception as exc: self.fail("cloud_environment {0} could not be resolved: {1}".format(_cloud_environment, str(exc)), exception=traceback.format_exc()) - credentials = MSIAuthentication(client_id=client_id, cloud_environment=cloud_environment) + client_id = client_id or self._get_env('client_id') credential = managed_identity.ManagedIdentityCredential(client_id=client_id, cloud_environment=cloud_environment) subscription_id = subscription_id or self._get_env('subscription_id') if not subscription_id: @@ -1653,8 +1619,7 @@ class AzureRMAuth(object): self.fail("Failed to get MSI token: {0}. " "Please check whether your machine enabled MSI or grant access to any subscription.".format(str(exc))) return { - 'credentials': credentials, - 'credential': credential, + 'credentials': credential, 'subscription_id': subscription_id, 'cloud_environment': cloud_environment, 'auth_source': 'msi' @@ -1669,12 +1634,13 @@ class AzureRMAuth(object): except Exception as exc: self.fail("Failed to load CLI profile {0}.".format(str(exc))) - credentials, subscription_id, tenant = profile.get_login_credentials( - subscription_id=subscription_id, resource=resource) + cred, subscription_id, tenant = profile.get_login_credentials( + subscription_id=subscription_id) cloud_environment = get_cli_active_cloud() + az_cli = AzureCliCredential() cli_credentials = { - 'credentials': credentials, + 'credentials': az_cli if self.is_ad_resource else cred, 'subscription_id': subscription_id, 'cloud_environment': cloud_environment } @@ -1762,42 +1728,6 @@ class AzureRMAuth(object): return None - def acquire_token_with_username_password(self, authority, username, password, client_id, tenant): - authority_uri = authority - - if tenant is not None: - authority_uri = authority + '/' + tenant - - context = ClientApplication(client_id=client_id, authority=authority_uri) - base_url = self._cloud_environment.endpoints.resource_manager - if not base_url.endswith("/"): - base_url += "/" - scopes = [base_url + ".default"] - token_response = context.acquire_token_by_username_password(username, password, scopes) - - return AADTokenCredentials(token_response) - - def acquire_token_with_client_certificate(self, authority, x509_private_key_path, thumbprint, client_id, tenant): - authority_uri = authority - - if tenant is not None: - authority_uri = authority + '/' + tenant - - x509_private_key = None - with open(x509_private_key_path, 'r') as pem_file: - x509_private_key = pem_file.read() - - base_url = self._cloud_environment.endpoints.resource_manager - if not base_url.endswith("/"): - base_url += "/" - scopes = [base_url + ".default"] - client_credential = {"thumbprint": thumbprint, "private_key": x509_private_key} - context = ConfidentialClientApplication(client_id=client_id, authority=authority_uri, client_credential=client_credential) - - token_response = context.acquire_token_for_client(scopes=scopes) - - return AADTokenCredentials(token_response) - def log(self, msg, pretty_print=False): pass # Use only during module development diff --git a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_rest.py b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_rest.py index 6acb1e7b9..bc740824f 100644 --- a/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_rest.py +++ b/ansible_collections/azure/azcollection/plugins/module_utils/azure_rm_common_rest.py @@ -82,7 +82,7 @@ class GenericRestClient(object): response = self._client.send_request(request, **operation_config) if response.status_code not in expected_status_codes: - exp = SendRequestException(response, response.status_code) + exp = SendRequestException(response.text(), response.status_code) raise exp elif response.status_code == 202 and polling_timeout > 0: def get_long_running_output(response): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_accesstoken_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_accesstoken_info.py new file mode 100644 index 000000000..cf9569868 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_accesstoken_info.py @@ -0,0 +1,126 @@ +#!/usr/bin/python +# +# Copyright (c) 2023 Patrick Uiterwijk <@puiterwijk> +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_accesstoken_info + +version_added: "1.19.0" + +short_description: Get Azure API access token + +description: + - Get an access token for Azure APIs. + +options: + scopes: + description: + - The scopes to request. + type: list + elements: str + required: True + claims: + description: + - Additional claims required in the token. + type: list + elements: str + token_tenant_id: + description: + - Tenant to include in the token request. + type: str + enable_cae: + description: + - Whether to enable Continuous Access Evaluation (CAE) for the requested token. + default: false + type: bool + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - Patrick Uiterwijk (@puiterwijk) +''' + +EXAMPLES = ''' +- name: Get access token for Microsoft Graph + azure.azcollection.azure_rm_accesstoken_info: + scopes: + - https://graph.microsoft.com/.default +''' + +RETURN = ''' +access_token: + description: + - API access token. + returned: success + type: str + sample: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyfQ.L8i6g3PfcHlioHCCPURC9pmXT7gdJpx3kOoyAfNUwCc +expires_on: + description: + - Timestamp the token expires on. + returned: success + type: int + sample: 1699337824 +''' + + +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + + +class AzureRMAccessToken(AzureRMModuleBase): + + def __init__(self): + + self.module_arg_spec = dict( + scopes=dict(type='list', elements='str', required=True), + claims=dict(type='list', elements='str'), + token_tenant_id=dict(type='str'), + enable_cae=dict(type='bool', default=False), + ) + + self.scopes = None + self.claims = None + self.token_tenant_id = None + self.enable_cae = False + + self.results = dict(changed=False) + + super(AzureRMAccessToken, self).__init__(derived_arg_spec=self.module_arg_spec, + supports_check_mode=True, + supports_tags=False, + is_ad_resource=False) + + def exec_module(self, **kwargs): + for key in list(self.module_arg_spec.keys()): + setattr(self, key, kwargs[key]) + + claims = None + if self.claims is not None: + claims = ' '.join(self.claims) + + cred = self.azure_auth.azure_credential_track2 + token = cred.get_token( + *self.scopes, + claims=claims, + tenant_id=self.token_tenant_id, + enable_cae=self.enable_cae, + ) + + self.results['access_token'] = token.token + self.results['expires_on'] = token.expires_on + return self.results + + +def main(): + AzureRMAccessToken() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_account_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_account_info.py index 5061604e2..a3f2109bd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_account_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_account_info.py @@ -102,14 +102,13 @@ account_info: try: - from azure.graphrbac import GraphRbacManagementClient - from azure.graphrbac.models import GraphErrorException + import asyncio + from msgraph.generated.education.me.user.user_request_builder import UserRequestBuilder except ImportError: # This is handled in azure_rm_common pass from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMAuth class AzureRMAccountInfo(AzureRMModuleBase): @@ -126,19 +125,15 @@ class AzureRMAccountInfo(AzureRMModuleBase): # Different return info is gathered using 2 different clients # 1. All except "user" section of the return value uses azure.mgmt.subsctiption.operations.subscriptionoperations - # 2. "user" section of the return value uses different client (graphrbac) + # 2. "user" section of the return value uses different client (GraphServiceClient) super(AzureRMAccountInfo, self).__init__(derived_arg_spec=self.module_arg_spec, supports_check_mode=True, supports_tags=False, - is_ad_resource=False) + is_ad_resource=True) def exec_module(self, **kwargs): - - result = [] - result = self.list_items() - - self.results['account_info'] = result + self.results['account_info'] = self.list_items() return self.results def list_items(self): @@ -179,7 +174,7 @@ class AzureRMAccountInfo(AzureRMModuleBase): results['state'] = subscription_list_response[0].state results['managedByTenants'] = self.get_managed_by_tenants_list(subscription_list_response[0].managed_by_tenants) results['environmentName'] = self.azure_auth._cloud_environment.name - results['user'] = self.get_aduser_info(subscription_list_response[0].tenant_id) + results['user'] = self.get_aduser_info() return results @@ -187,33 +182,32 @@ class AzureRMAccountInfo(AzureRMModuleBase): return [dict(tenantId=item.tenant_id) for item in object_list] - def get_aduser_info(self, tenant_id): + def get_aduser_info(self): - # Create GraphRbacManagementClient for getting + # Create GraphServiceClient for getting # "user": { # "name": "mandar123456@abcdefg.onmicrosoft.com", - # "type": "user"self. + # "type": "Member" # } - # Makes use of azure graphrbac - # https://docs.microsoft.com/en-us/python/api/overview/azure/microsoft-graph?view=azure-python#client-library + # Makes use of azure MSGraph + # https://learn.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0&tabs=http user = {} - self.azure_auth_graphrbac = AzureRMAuth(is_ad_resource=True) - cred = self.azure_auth_graphrbac.azure_credentials - base_url = self.azure_auth_graphrbac._cloud_environment.endpoints.active_directory_graph_resource_id - client = GraphRbacManagementClient(cred, tenant_id, base_url) - - try: - user_info = client.signed_in_user.get() - user['name'] = user_info.user_principal_name - user['type'] = user_info.object_type - - except GraphErrorException as e: - self.fail("failed to get ad user info {0}".format(str(e))) + user_info = asyncio.get_event_loop().run_until_complete(self.getAccount()) + user['name'] = user_info.user_principal_name + user['type'] = user_info.user_type return user + async def getAccount(self): + return await self.get_msgraph_client().me.get( + request_configuration=UserRequestBuilder.UserRequestBuilderGetRequestConfiguration( + query_parameters=UserRequestBuilder.UserRequestBuilderGetQueryParameters( + select=["userType", "userPrincipalName", "postalCode", "identities"], ), + ) + ) + def main(): AzureRMAccountInfo() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication.py index 9f21728fc..b428463aa 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication.py @@ -5,8 +5,8 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function -__metaclass__ = type +__metaclass__ = type DOCUMENTATION = ''' --- @@ -20,12 +20,6 @@ description: - Manage Azure Active Directory application. options: - tenant: - description: - - The tenant ID. - type: str - required: True - app_id: description: - Application ID. @@ -34,6 +28,7 @@ options: display_name: description: - The display name of the application. + required: true type: str app_roles: @@ -74,11 +69,24 @@ options: - Any other character, including the space character, are not allowed. type: str - available_to_other_tenants: + sign_in_audience: description: - The application can be used from any Azure AD tenants. - type: bool + - Microsoft Graph SDK deprecate I(available_to_other_tenants), replace by I(sign_in_audience). + - Refer to link U(https://learn.microsoft.com/en-us/graph/migrate-azure-ad-graph-property-differences#application-property-differences) + type: str + choices: + - AzureADMyOrg + - AzureADMultipleOrgs + - AzureADandPersonalMicrosoftAccount + - PersonalMicrosoftAccount + available_to_other_tenants: + description: + - (Deprecated) The application can be used from any Azure AD tenants. + - This parameter was not supported after the migration to Microsoft Graph and was replaced by I(sign_in_audience). + - It will deprecated in next version(V3.0.0). + type: bool credential_description: description: - The description of the password. @@ -170,8 +178,27 @@ options: - App password, aka 'client secret'. type: str - reply_urls: + web_reply_urls: description: + - The web redirect urls. + - Space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. + - The value does not need to be a physical endpoint, but must be a valid URI. + type: list + elements: str + aliases: + - reply_urls + + spa_reply_urls: + description: + - The spa redirect urls. + - Space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. + - The value does not need to be a physical endpoint, but must be a valid URI. + type: list + elements: str + + public_client_reply_urls: + description: + - The public client redirect urls. - Space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. - The value does not need to be a physical endpoint, but must be a valid URI. type: list @@ -236,14 +263,24 @@ author: EXAMPLES = ''' - name: Create ad application azure_rm_adapplication: - tenant: "{{ tenant_id }}" display_name: "{{ display_name }}" +- name: Create ad application with multi redirect urls + azure_rm_adapplication: + display_name: "{{ display_name }}" + web_reply_urls: + - https://web01.com + spa_reply_urls: + - https://spa01.com + - https://spa02.com + public_client_reply_urls: + - https://public01.com + - https://public02.com + - name: Create application with more parameter azure_rm_adapplication: - tenant: "{{ tenant_id }}" display_name: "{{ display_name }}" - available_to_other_tenants: false + sign_in_audience: AzureADandPersonalMicrosoftAccount credential_description: "for test" end_date: 2021-10-01 start_date: 2021-05-18 @@ -251,7 +288,6 @@ EXAMPLES = ''' - name: delete ad application azure_rm_adapplication: - tenant: "{{ tenant_id }}" app_id: "{{ app_id }}" state: absent ''' @@ -281,12 +317,18 @@ output: returned: always type: str sample: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + sign_in_audience: + description: + - The application can be used from any Azure AD tenants. + returned: always + type: str + sample: AzureADandPersonalMicrosoftAccount available_to_other_tenants: description: - The application can be used from any Azure AD tenants. returned: always - type: bool - sample: false + type: str + sample: AzureADandPersonalMicrosoftAccount homepage: description: - The url where users can sign in and use your app. @@ -311,8 +353,23 @@ output: returned: always type: list sample: [] - reply_urls: + public_client_reply_urls: + description: + - The public client redirect urls. + - Space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. + returned: always + type: list + sample: [] + web_reply_urls: description: + - The web redirect urls. + - Space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. + returned: always + type: list + sample: [] + spa_reply_urls: + description: + - The spa redirect urls. - Space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. returned: always type: list @@ -322,17 +379,22 @@ output: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt try: - from azure.graphrbac.models import GraphErrorException import datetime - from dateutil.relativedelta import relativedelta import dateutil.parser - from azure.graphrbac.models import ApplicationCreateParameters import uuid - from azure.graphrbac.models import ResourceAccess - from azure.graphrbac.models import RequiredResourceAccess - from azure.graphrbac.models import AppRole - from azure.graphrbac.models import PasswordCredential, KeyCredential - from azure.graphrbac.models import ApplicationUpdateParameters + import asyncio + from dateutil.relativedelta import relativedelta + from msgraph.generated.applications.applications_request_builder import ApplicationsRequestBuilder + from msgraph.generated.models.application import Application + from msgraph.generated.models.password_credential import PasswordCredential + from msgraph.generated.models.key_credential import KeyCredential + from msgraph.generated.models.required_resource_access import RequiredResourceAccess + from msgraph.generated.models.resource_access import ResourceAccess + from msgraph.generated.models.app_role import AppRole + from msgraph.generated.models.web_application import WebApplication + from msgraph.generated.models.spa_application import SpaApplication + from msgraph.generated.models.public_client_application import PublicClientApplication + from msgraph.generated.models.implicit_grant_settings import ImplicitGrantSettings except ImportError: # This is handled in azure_rm_common pass @@ -396,31 +458,40 @@ class AzureRMADApplication(AzureRMModuleBaseExt): def __init__(self): self.module_arg_spec = dict( - tenant=dict(type='str', required=True), app_id=dict(type='str'), - display_name=dict(type='str'), + display_name=dict(type='str', required=True), app_roles=dict(type='list', elements='dict', options=app_role_spec), - available_to_other_tenants=dict(type='bool'), + sign_in_audience=dict( + type='str', + choices=['AzureADMyOrg', 'AzureADMultipleOrgs', 'AzureADandPersonalMicrosoftAccount', 'PersonalMicrosoftAccount'] + ), + available_to_other_tenants=dict( + type='bool', + removed_in_version='3.0.0', + removed_from_collection='azure.azcollection' + ), credential_description=dict(type='str'), end_date=dict(type='str'), homepage=dict(type='str'), allow_guests_sign_in=dict(type='bool'), identifier_uris=dict(type='list', elements='str'), - key_type=dict(type='str', default='AsymmetricX509Cert', choices=['AsymmetricX509Cert', 'Password', 'Symmetric']), + key_type=dict(type='str', default='AsymmetricX509Cert', + choices=['AsymmetricX509Cert', 'Password', 'Symmetric']), key_usage=dict(type='str', default='Verify', choices=['Sign', 'Verify']), key_value=dict(type='str', no_log=True), native_app=dict(type='bool'), oauth2_allow_implicit_flow=dict(type='bool'), optional_claims=dict(type='list', elements='dict', options=optional_claims_spec), password=dict(type='str', no_log=True), - reply_urls=dict(type='list', elements='str'), + public_client_reply_urls=dict(type='list', elements='str'), + web_reply_urls=dict(type='list', elements='str', aliases=['reply_urls']), + spa_reply_urls=dict(type='list', elements='str'), start_date=dict(type='str'), required_resource_accesses=dict(type='list', elements='dict', options=required_resource_accesses_spec), state=dict(type='str', default='present', choices=['present', 'absent']), ) self.state = None - self.tenant = None self.app_id = None self.display_name = None self.app_roles = None @@ -436,11 +507,15 @@ class AzureRMADApplication(AzureRMModuleBaseExt): self.oauth2_allow_implicit_flow = None self.optional_claims = None self.password = None - self.reply_urls = None + self.public_client_reply_urls = None + self.spa_reply_urls = None + self.web_reply_urls = None self.start_date = None self.required_resource_accesses = None self.allow_guests_sign_in = None self.results = dict(changed=False) + self._client = None + self.sign_in_audience = None super(AzureRMADApplication, self).__init__(derived_arg_spec=self.module_arg_spec, supports_check_mode=False, @@ -448,12 +523,11 @@ class AzureRMADApplication(AzureRMModuleBaseExt): is_ad_resource=True) def exec_module(self, **kwargs): - + self._client = self.get_msgraph_client() for key in list(self.module_arg_spec.keys()): setattr(self, key, kwargs[key]) response = self.get_resource() - if response: if self.state == 'present': if self.check_update(response): @@ -475,90 +549,113 @@ class AzureRMADApplication(AzureRMModuleBaseExt): if self.identifier_uris: self.fail("'identifier_uris' is not required for creating a native application") else: - password_creds, key_creds = self.build_application_creds(self.password, self.key_value, self.key_type, self.key_usage, - self.start_date, self.end_date, self.credential_description) + password_creds, key_creds = self.build_application_creds(self.password, self.key_value, self.key_type, + self.key_usage, + self.start_date, self.end_date, + self.credential_description) if self.required_resource_accesses: required_accesses = self.build_application_accesses(self.required_resource_accesses) if self.app_roles: app_roles = self.build_app_roles(self.app_roles) - client = self.get_graphrbac_client(self.tenant) - app_create_param = ApplicationCreateParameters(available_to_other_tenants=self.available_to_other_tenants, - display_name=self.display_name, - identifier_uris=self.identifier_uris, - homepage=self.homepage, - reply_urls=self.reply_urls, - key_credentials=key_creds, - password_credentials=password_creds, - oauth2_allow_implicit_flow=self.oauth2_allow_implicit_flow, - required_resource_access=required_accesses, - app_roles=app_roles, - allow_guests_sign_in=self.allow_guests_sign_in, - optional_claims=self.optional_claims) - response = client.applications.create(app_create_param) + create_app = Application( + sign_in_audience=self.sign_in_audience, + web=WebApplication( + home_page_url=self.homepage, + redirect_uris=self.web_reply_urls, + implicit_grant_settings=ImplicitGrantSettings( + enable_access_token_issuance=self.oauth2_allow_implicit_flow, + ), + ), + spa=SpaApplication(redirect_uris=self.spa_reply_urls), + public_client=PublicClientApplication(redirect_uris=self.public_client_reply_urls), + display_name=self.display_name, + identifier_uris=self.identifier_uris, + key_credentials=key_creds, + password_credentials=password_creds, + required_resource_access=required_accesses, + app_roles=app_roles, + optional_claims=self.optional_claims + # allow_guests_sign_in=self.allow_guests_sign_in, + ) + response = asyncio.get_event_loop().run_until_complete(self.create_application(create_app)) self.results['changed'] = True self.results.update(self.to_dict(response)) return response - except GraphErrorException as ge: - self.fail("Error creating application, display_name {0} - {1}".format(self.display_name, str(ge))) + except Exception as ge: + self.fail("Error creating application, display_name: {0} - {1}".format(self.display_name, str(ge))) def update_resource(self, old_response): try: - client = self.get_graphrbac_client(self.tenant) key_creds, password_creds, required_accesses, app_roles, optional_claims = None, None, None, None, None if self.native_app: if self.identifier_uris: self.fail("'identifier_uris' is not required for creating a native application") else: - password_creds, key_creds = self.build_application_creds(self.password, self.key_value, self.key_type, self.key_usage, - self.start_date, self.end_date, self.credential_description) + password_creds, key_creds = self.build_application_creds(self.password, self.key_value, self.key_type, + self.key_usage, + self.start_date, self.end_date, + self.credential_description) if self.required_resource_accesses: required_accesses = self.build_application_accesses(self.required_resource_accesses) if self.app_roles: app_roles = self.build_app_roles(self.app_roles) - app_update_param = ApplicationUpdateParameters(available_to_other_tenants=self.available_to_other_tenants, - display_name=self.display_name, - identifier_uris=self.identifier_uris, - homepage=self.homepage, - reply_urls=self.reply_urls, - key_credentials=key_creds, - password_credentials=password_creds, - oauth2_allow_implicit_flow=self.oauth2_allow_implicit_flow, - required_resource_access=required_accesses, - allow_guests_sign_in=self.allow_guests_sign_in, - app_roles=app_roles, - optional_claims=self.optional_claims) - client.applications.patch(old_response['object_id'], app_update_param) + + app_update_param = Application( + sign_in_audience=self.sign_in_audience, + web=WebApplication( + home_page_url=self.homepage, + redirect_uris=self.web_reply_urls, + implicit_grant_settings=ImplicitGrantSettings( + enable_access_token_issuance=self.oauth2_allow_implicit_flow, + ), + ), + spa=SpaApplication(redirect_uris=self.spa_reply_urls), + public_client=PublicClientApplication(redirect_uris=self.public_client_reply_urls), + display_name=self.display_name, + identifier_uris=self.identifier_uris, + key_credentials=key_creds, + password_credentials=password_creds, + required_resource_access=required_accesses, + # allow_guests_sign_in=self.allow_guests_sign_in, + app_roles=app_roles, + optional_claims=self.optional_claims) + asyncio.get_event_loop().run_until_complete(self.update_application( + obj_id=old_response['object_id'], update_app=app_update_param)) + self.results['changed'] = True self.results.update(self.get_resource()) - except GraphErrorException as ge: + except Exception as ge: self.fail("Error updating the application app_id {0} - {1}".format(self.app_id, str(ge))) def delete_resource(self, response): try: - client = self.get_graphrbac_client(self.tenant) - client.applications.delete(response.get('object_id')) + asyncio.get_event_loop().run_until_complete(self.delete_application(response.get('object_id'))) self.results['changed'] = True return True - except GraphErrorException as ge: - self.fail("Error deleting application app_id {0} display_name {1} - {2}".format(self.app_id, self.display_name, str(ge))) + except Exception as ge: + self.fail( + "Error deleting application app_id {0} display_name {1} - {2}".format(self.app_id, self.display_name, + str(ge))) def get_resource(self): try: - client = self.get_graphrbac_client(self.tenant) existing_apps = [] if self.app_id: - existing_apps = list(client.applications.list(filter="appId eq '{0}'".format(self.app_id))) + ret = asyncio.get_event_loop().run_until_complete(self.get_application_by_app_id(self.app_id)) + existing_apps = ret.value + if not existing_apps: return False result = existing_apps[0] return self.to_dict(result) - except GraphErrorException as ge: - self.log("Did not find the graph instance instance {0} - {1}".format(self.app_id, str(ge))) - return False + except Exception as ge: + self.fail(ge) + # self.log("Did not find the graph instance instance {0} - {1}".format(self.app_id, str(ge))) + # return False def check_update(self, response): for key in list(self.module_arg_spec.keys()): @@ -575,19 +672,22 @@ class AzureRMADApplication(AzureRMModuleBaseExt): 'is_enabled': app_role.is_enabled, 'value': app_role.value, "description": app_role.description - }for app_role in object.app_roles] + } for app_role in object.app_roles] return dict( app_id=object.app_id, - object_id=object.object_id, + object_id=object.id, display_name=object.display_name, app_roles=app_roles, - available_to_other_tenants=object.available_to_other_tenants, - homepage=object.homepage, + available_to_other_tenants=object.sign_in_audience, + sign_in_audience=object.sign_in_audience, + homepage=object.web.home_page_url, identifier_uris=object.identifier_uris, - oauth2_allow_implicit_flow=object.oauth2_allow_implicit_flow, + oauth2_allow_implicit_flow=object.web.implicit_grant_settings.enable_access_token_issuance, optional_claims=object.optional_claims, - allow_guests_sign_in=object.allow_guests_sign_in, - reply_urls=object.reply_urls + # allow_guests_sign_in=object.allow_guests_sign_in, + web_reply_urls=object.web.redirect_uris, + spa_reply_urls=object.spa.redirect_uris, + public_client_reply_urls=object.public_client.redirect_uris ) def build_application_creds(self, password=None, key_value=None, key_type=None, key_usage=None, @@ -615,14 +715,16 @@ class AzureRMADApplication(AzureRMModuleBaseExt): password_creds = None key_creds = None if password: - password_creds = [PasswordCredential(start_date=start_date, end_date=end_date, key_id=str(self.gen_guid()), - value=password, custom_key_identifier=custom_key_id)] + password_creds = [PasswordCredential(start_date_time=start_date, end_date_time=end_date, + key_id=self.gen_guid(), secret_text=password, + custom_key_identifier=custom_key_id)] # value ? secret_text elif key_value: key_creds = [ - KeyCredential(start_date=start_date, end_date=end_date, key_id=str(self.gen_guid()), value=key_value, + KeyCredential(start_date_time=start_date, end_date_time=end_date, key_id=self.gen_guid(), key=key_value, + # value ? key usage=key_usage, type=key_type, custom_key_identifier=custom_key_id)] - return (password_creds, key_creds) + return password_creds, key_creds def encode_custom_key_description(self, key_description): # utf16 is used by AAD portal. Do not change it to other random encoding @@ -640,7 +742,6 @@ class AzureRMADApplication(AzureRMModuleBaseExt): self.log('Getting "requiredResourceAccess" from a full manifest') required_resource_accesses = required_resource_accesses.get('required_resource_access', []) for x in required_resource_accesses: - accesses = [ResourceAccess(id=y['id'], type=y['type']) for y in x['resource_access']] required_accesses.append(RequiredResourceAccess(resource_app_id=x['resource_app_id'], resource_access=accesses)) @@ -657,10 +758,34 @@ class AzureRMADApplication(AzureRMModuleBaseExt): role = AppRole(id=x.get('id', None) or self.gen_guid(), allowed_member_types=x.get('allowed_member_types', None), description=x.get('description', None), display_name=x.get('display_name', None), - is_enabled=x.get('is_enabled', None), value=x.get('value', None)) + is_enabled=x.get('is_enabled', None), value=x.get('value', None)) # value ? additional_data result.append(role) return result + async def create_application(self, creat_app): + return await self._client.applications.post(body=creat_app) + + async def update_application(self, obj_id, update_app): + return await self._client.applications.by_application_id(obj_id).patch(body=update_app) + + async def get_application_by_app_id(self, app_id): + request_configuration = ApplicationsRequestBuilder.ApplicationsRequestBuilderGetRequestConfiguration( + query_parameters=ApplicationsRequestBuilder.ApplicationsRequestBuilderGetQueryParameters( + filter=(" appId eq '{0}'".format(app_id)), ), + ) + + return await self._client.applications.get(request_configuration=request_configuration) + + async def delete_application(self, obj_id): + await self._client.applications.by_application_id(obj_id).delete() + + async def get_applications(self, filters): + request_configuration = ApplicationsRequestBuilder.ApplicationsRequestBuilderGetRequestConfiguration( + query_parameters=ApplicationsRequestBuilder.ApplicationsRequestBuilderGetQueryParameters( + filter=(' and '.join(filters)) + )) + return await self._client.applications.get(request_configuration=request_configuration) + def main(): AzureRMADApplication() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication_info.py index 939058815..167b82552 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adapplication_info.py @@ -6,8 +6,8 @@ from __future__ import absolute_import, division, print_function -__metaclass__ = type +__metaclass__ = type DOCUMENTATION = ''' module: azure_rm_adapplication_info @@ -24,18 +24,17 @@ options: description: - The application ID. type: str - tenant: - description: - - The tenant ID. - type: str - required: True object_id: description: - - It's application's object ID. + - The application's object ID. type: str identifier_uri: description: - - It's identifier_uri's object ID. + - The identifier_uri's object ID. + type: str + app_display_name: + description: + - The applications' Name. type: str extends_documentation_fragment: @@ -45,23 +44,25 @@ author: haiyuan_zhang (@haiyuazhang) Fred-sun (@Fred-sun) guopeng_lin (@guopenglin) + Xu Zhang (@xuzhang) ''' EXAMPLES = ''' - name: get ad app info by App ID azure_rm_adapplication_info: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" - name: get ad app info ---- by object ID azure_rm_adapplication_info: object_id: "{{ object_id }}" - tenant: "{{ tenant_id }}" - name: get ad app info ---- by identifier uri azure_rm_adapplication_info: identifier_uri: "{{ identifier_uri }}" - tenant: "{{ tenant_id }}" + +- name: get ad app info ---- by display name + azure_rm_adapplication_info: + app_display_name: "{{ display_name }}" ''' RETURN = ''' @@ -95,12 +96,47 @@ applications: returned: always type: str sample: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + sign_in_audience: + description: + - The application can be used from any Azure AD tenants + type: str + returned: always + sample: AzureADandPersonalMicrosoftAccount + available_to_other_tenants: + description: + - The application can be used from any Azure AD tenants + type: str + returned: always + sample: AzureADandPersonalMicrosoftAccount + public_client_reply_urls: + description: + - The public client redirect urls. + - Space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. + returned: always + type: list + sample: [] + web_reply_urls: + description: + - The web redirect urls. + - Space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. + returned: always + type: list + sample: [] + spa_reply_urls: + description: + - The spa redirect urls. + - Space-separated URIs to which Azure AD will redirect in response to an OAuth 2.0 request. + returned: always + type: list + sample: [] ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from azure.graphrbac.models import GraphErrorException + import asyncio + from msgraph.generated.applications.applications_request_builder import ApplicationsRequestBuilder + from kiota_abstractions.api_error import APIError except ImportError: # This is handled in azure_rm_common pass @@ -110,25 +146,17 @@ class AzureRMADApplicationInfo(AzureRMModuleBase): def __init__(self): self.module_arg_spec = dict( - app_id=dict( - type='str' - ), - object_id=dict( - type='str' - ), - identifier_uri=dict( - type='str' - ), - tenant=dict( - type='str', - required=True - ) + app_id=dict(type='str'), + object_id=dict(type='str'), + identifier_uri=dict(type='str'), + app_display_name=dict(type='str') ) - self.tenant = None self.app_id = None + self.app_display_name = None self.object_id = None self.identifier_uri = None self.results = dict(changed=False) + self._client = None super(AzureRMADApplicationInfo, self).__init__(derived_arg_spec=self.module_arg_spec, supports_check_mode=True, supports_tags=False, @@ -139,21 +167,26 @@ class AzureRMADApplicationInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) applications = [] + try: - client = self.get_graphrbac_client(self.tenant) + self._client = self.get_msgraph_client() if self.object_id: - applications = [client.applications.get(self.object_id)] + applications = [asyncio.get_event_loop().run_until_complete(self.get_application(self.object_id))] else: sub_filters = [] if self.identifier_uri: sub_filters.append("identifierUris/any(s:s eq '{0}')".format(self.identifier_uri)) if self.app_id: sub_filters.append("appId eq '{0}'".format(self.app_id)) - # applications = client.applications.list(filter=(' and '.join(sub_filters))) - applications = list(client.applications.list(filter=(' and '.join(sub_filters)))) - + if self.app_display_name: + sub_filters.append("displayName eq '{0}'".format(self.app_display_name)) + apps = asyncio.get_event_loop().run_until_complete(self.get_applications(sub_filters)) + applications = list(apps) self.results['applications'] = [self.to_dict(app) for app in applications] - except GraphErrorException as ge: + except APIError as e: + if e.response_status_code != 404: + self.fail("failed to get application info {0}".format(str(e))) + except Exception as ge: self.fail("failed to get application info {0}".format(str(ge))) return self.results @@ -161,11 +194,46 @@ class AzureRMADApplicationInfo(AzureRMModuleBase): def to_dict(self, object): return dict( app_id=object.app_id, - object_id=object.object_id, + object_id=object.id, app_display_name=object.display_name, - identifier_uris=object.identifier_uris + identifier_uris=object.identifier_uris, + available_to_other_tenants=object.sign_in_audience, + sign_in_audience=object.sign_in_audience, + web_reply_urls=object.web.redirect_uris, + spa_reply_urls=object.spa.redirect_uris, + public_client_reply_urls=object.public_client.redirect_uris ) + async def get_application(self, obj_id): + return await self._client.applications.by_application_id(obj_id).get() + + async def get_applications(self, sub_filters): + if sub_filters: + request_configuration = ApplicationsRequestBuilder.ApplicationsRequestBuilderGetRequestConfiguration( + query_parameters=ApplicationsRequestBuilder.ApplicationsRequestBuilderGetQueryParameters( + filter=(' and '.join(sub_filters)), + ), + ) + applications = await self._client.applications.get(request_configuration=request_configuration) + return applications.value + else: + applications_list = [] + applications = await self._client.applications.get() + for app in applications.value: + applications_list.append(app) + + if applications.odata_next_link: + next_link = applications.odata_next_link + else: + next_link = None + + while next_link: + applications = await self._client.applications.with_url(next_link).get() + next_link = applications.odata_next_link + for app in applications.value: + applications_list.append(app) + return applications_list + def main(): AzureRMADApplicationInfo() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup.py index 812b6953c..1693794a7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup.py @@ -5,6 +5,7 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function + __metaclass__ = type DOCUMENTATION = ''' @@ -14,11 +15,6 @@ short_description: Manage Azure Active Directory group description: - Create, update or delete Azure Active Directory group. options: - tenant: - description: - - The tenant ID. - type: str - required: True state: description: - Assert the state of the resource group. Use C(present) to create or update and C(absent) to delete. @@ -67,6 +63,10 @@ options: - The azure ad objects asserted to not be owners of the group. type: list elements: str + description: + description: + - An optional description for the group. + type: str extends_documentation_fragment: - azure.azcollection.azure author: @@ -76,46 +76,41 @@ author: EXAMPLES = ''' - name: Create Group azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx display_name: "Group-Name" mail_nickname: "Group-Mail-Nickname" + description: 'fortest' state: 'present' - name: Delete Group using display_name and mail_nickname azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx display_name: "Group-Name" mail_nickname: "Group-Mail-Nickname" state: 'absent' - name: Delete Group using object_id azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx state: 'absent' - name: Ensure Users are Members of a Group using display_name and mail_nickname azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx display_name: "Group-Name" mail_nickname: "Group-Mail-Nickname" state: 'present' present_members: - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" + - "{{ ad_object_1_object_id }}" + - "{{ ad_object_2_object_id }}" - name: Ensure Users are Members of a Group using object_id azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx state: 'present' present_members: - - "https://graph.windows.net/{{ ad_object_1_tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" - - "https://graph.windows.net/{{ ad_object_2_tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" + - "{{ ad_object_1_object_id }}" + - "{{ ad_object_2_object_id }}" - name: Ensure Users are not Members of a Group using display_name and mail_nickname azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx display_name: "Group-Name" mail_nickname: "Group-Mail-Nickname" state: 'present' @@ -124,7 +119,6 @@ EXAMPLES = ''' - name: Ensure Users are Members of a Group using object_id azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx state: 'present' absent_members: @@ -132,26 +126,23 @@ EXAMPLES = ''' - name: Ensure Users are Owners of a Group using display_name and mail_nickname azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx display_name: "Group-Name" mail_nickname: "Group-Mail-Nickname" state: 'present' present_owners: - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" + - "{{ ad_object_1_object_id }}" + - "{{ ad_object_2_object_id }}" - name: Ensure Users are Owners of a Group using object_id azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx state: 'present' present_owners: - - "https://graph.windows.net/{{ ad_object_1_tenant_id }}/directoryObjects/{{ ad_object_1_object_id }}" - - "https://graph.windows.net/{{ ad_object_2_tenant_id }}/directoryObjects/{{ ad_object_2_object_id }}" + - "{{ ad_object_1_object_id }}" + - "{{ ad_object_2_object_id }}" - name: Ensure Users are not Owners of a Group using display_name and mail_nickname azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx display_name: "Group-Name" mail_nickname: "Group-Mail-Nickname" state: 'present' @@ -161,7 +152,6 @@ EXAMPLES = ''' - name: Ensure Users are Owners of a Group using object_id azure_rm_adgroup: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx state: 'present' absent_owners: @@ -216,13 +206,23 @@ group_members: - The members of the group. returned: always type: list +description: + description: + - An optional description for the group. + type: str + returned: always + sample: 'fortest' ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from azure.graphrbac.models import GraphErrorException - from azure.graphrbac.models import GroupCreateParameters + import asyncio + from msgraph.generated.groups.groups_request_builder import GroupsRequestBuilder + from msgraph.generated.models.group import Group + from msgraph.generated.groups.item.transitive_members.transitive_members_request_builder import \ + TransitiveMembersRequestBuilder + from msgraph.generated.models.reference_create import ReferenceCreate except ImportError: # This is handled in azure_rm_common pass @@ -239,7 +239,7 @@ class AzureRMADGroup(AzureRMModuleBase): present_owners=dict(type='list', elements='str'), absent_members=dict(type='list', elements='str'), absent_owners=dict(type='list', elements='str'), - tenant=dict(type='str', required=True), + description=dict(type='str'), state=dict( type='str', default='present', @@ -247,7 +247,6 @@ class AzureRMADGroup(AzureRMModuleBase): ), ) - self.tenant = None self.display_name = None self.mail_nickname = None self.object_id = None @@ -257,6 +256,7 @@ class AzureRMADGroup(AzureRMModuleBase): self.absent_owners = [] self.state = None self.results = dict(changed=False) + self._client = None super(AzureRMADGroup, self).__init__(derived_arg_spec=self.module_arg_spec, supports_check_mode=False, @@ -264,7 +264,6 @@ class AzureRMADGroup(AzureRMModuleBase): is_ad_resource=True) def exec_module(self, **kwargs): - for key in list(self.module_arg_spec.keys()): setattr(self, key, kwargs[key]) @@ -272,53 +271,61 @@ class AzureRMADGroup(AzureRMModuleBase): ad_groups = [] try: - client = self.get_graphrbac_client(self.tenant) + self._client = self.get_msgraph_client() ad_groups = [] if self.display_name and self.mail_nickname: - ad_groups = list(client.groups.list(filter="displayName eq '{0}' and mailNickname eq '{1}'".format(self.display_name, self.mail_nickname))) - + filter = "displayName eq '{0}' and mailNickname eq '{1}'".format(self.display_name, self.mail_nickname) + ad_groups = asyncio.get_event_loop().run_until_complete(self.get_group_list(filter)) if ad_groups: - self.object_id = ad_groups[0].object_id + self.object_id = ad_groups[0].id elif self.object_id: - ad_groups = [client.groups.get(self.object_id)] + ad_groups = [asyncio.get_event_loop().run_until_complete(self.get_group(self.object_id))] if ad_groups: if self.state == "present": self.results["changed"] = False elif self.state == "absent": - ad_groups = [client.groups.delete(self.object_id)] + asyncio.get_event_loop().run_until_complete(self.delete_group(self.object_id)) + ad_groups = [] self.results["changed"] = True else: if self.state == "present": if self.display_name and self.mail_nickname: - ad_groups = [client.groups.create(GroupCreateParameters(display_name=self.display_name, mail_nickname=self.mail_nickname))] + group = Group( + mail_enabled=False, + security_enabled=True, + group_types=[], + display_name=self.display_name, + mail_nickname=self.mail_nickname, + description=self.description + ) + + ad_groups = [asyncio.get_event_loop().run_until_complete(self.create_group(group))] self.results["changed"] = True else: - raise ValueError('The group does not exist. Both display_name : {0} and mail_nickname : {1} must be passed to create a new group' - .format(self.display_name, self.mail_nickname)) + raise ValueError( + 'The group does not exist. Both display_name : {0} and mail_nickname : {1} must be passed to create a new group' + .format(self.display_name, self.mail_nickname)) elif self.state == "absent": self.results["changed"] = False - if ad_groups[0] is not None: - self.update_members(ad_groups[0].object_id, client) - self.update_owners(ad_groups[0].object_id, client) - self.results.update(self.set_results(ad_groups[0], client)) + if ad_groups and ad_groups[0] is not None: + self.update_members(ad_groups[0].id) + self.update_owners(ad_groups[0].id) + self.results.update(self.set_results(ad_groups[0])) - except GraphErrorException as e: - self.fail(e) - except ValueError as e: + except Exception as e: self.fail(e) - return self.results - def update_members(self, group_id, client): - + def update_members(self, group_id): current_members = [] if self.present_members or self.absent_members: - current_members = [object.object_id for object in list(client.groups.get_group_members(group_id))] + ret = asyncio.get_event_loop().run_until_complete(self.get_group_members(group_id)) + current_members = [object.id for object in ret.value] if self.present_members: present_members_by_object_id = self.dictionary_from_object_urls(self.present_members) @@ -327,8 +334,8 @@ class AzureRMADGroup(AzureRMModuleBase): if members_to_add: for member_object_id in members_to_add: - client.groups.add_member(group_id, present_members_by_object_id[member_object_id]) - + asyncio.get_event_loop().run_until_complete( + self.add_group_member(group_id, present_members_by_object_id[member_object_id])) self.results["changed"] = True if self.absent_members: @@ -336,24 +343,25 @@ class AzureRMADGroup(AzureRMModuleBase): if members_to_remove: for member in members_to_remove: - client.groups.remove_member(group_id, member) + asyncio.get_event_loop().run_until_complete(self.delete_group_member(group_id, member)) self.results["changed"] = True - def update_owners(self, group_id, client): + def update_owners(self, group_id): current_owners = [] if self.present_owners or self.absent_owners: - current_owners = [object.object_id for object in list(client.groups.list_owners(group_id))] + ret = asyncio.get_event_loop().run_until_complete(self.get_group_owners(group_id)) + current_owners = [object.id for object in ret.value] if self.present_owners: present_owners_by_object_id = self.dictionary_from_object_urls(self.present_owners) - owners_to_add = list(set(present_owners_by_object_id.keys()) - set(current_owners)) if owners_to_add: for owner_object_id in owners_to_add: - client.groups.add_owner(group_id, present_owners_by_object_id[owner_object_id]) + asyncio.get_event_loop().run_until_complete( + self.add_gropup_owner(group_id, present_owners_by_object_id[owner_object_id])) self.results["changed"] = True if self.absent_owners: @@ -361,7 +369,7 @@ class AzureRMADGroup(AzureRMModuleBase): if owners_to_remove: for owner in owners_to_remove: - client.groups.remove_owner(group_id, owner) + asyncio.get_event_loop().run_until_complete(self.remove_gropup_owner(group_id, owner)) self.results["changed"] = True def dictionary_from_object_urls(self, object_urls): @@ -383,24 +391,25 @@ class AzureRMADGroup(AzureRMModuleBase): def serviceprincipal_to_dict(self, object): return dict( app_id=object.app_id, - object_id=object.object_id, + object_id=object.id, app_display_name=object.display_name, app_role_assignment_required=object.app_role_assignment_required ) def group_to_dict(self, object): return dict( - object_id=object.object_id, + object_id=object.id, display_name=object.display_name, mail_nickname=object.mail_nickname, mail_enabled=object.mail_enabled, security_enabled=object.security_enabled, - mail=object.mail + mail=object.mail, + description=object.description ) def user_to_dict(self, object): return dict( - object_id=object.object_id, + object_id=object.id, display_name=object.display_name, user_principal_name=object.user_principal_name, mail_nickname=object.mail_nickname, @@ -410,28 +419,92 @@ class AzureRMADGroup(AzureRMModuleBase): ) def result_to_dict(self, object): - if object.object_type == "Group": + if object.odata_type == "#microsoft.graph.group": return self.group_to_dict(object) - elif object.object_type == "User": + elif object.odata_type == "#microsoft.graph.user": return self.user_to_dict(object) - elif object.object_type == "Application": + elif object.odata_type == "#microsoft.graph.application": return self.application_to_dict(object) - elif object.object_type == "ServicePrincipal": + elif object.odata_type == "#microsoft.graph.servicePrincipal": return self.serviceprincipal_to_dict(object) else: - return object.object_type + return object.odata_type - def set_results(self, object, client): + def set_results(self, object): results = self.group_to_dict(object) if results["object_id"] and (self.present_owners or self.absent_owners): - results["group_owners"] = [self.result_to_dict(object) for object in list(client.groups.list_owners(results["object_id"]))] + ret = asyncio.get_event_loop().run_until_complete(self.get_group_owners(results["object_id"])) + results["group_owners"] = [self.result_to_dict(object) for object in ret.value] if results["object_id"] and (self.present_members or self.absent_members): - results["group_members"] = [self.result_to_dict(object) for object in list(client.groups.get_group_members(results["object_id"]))] + ret = asyncio.get_event_loop().run_until_complete(self.get_group_members(results["object_id"])) + results["group_members"] = [self.result_to_dict(object) for object in ret.value] return results + async def create_group(self, create_group): + return await self._client.groups.post(body=create_group) + + async def delete_group(self, group_id): + await self._client.groups.by_group_id(group_id).delete() + + async def get_group(self, group_id): + return await self._client.groups.by_group_id(group_id).get() + + async def get_group_list(self, filter=None): + if filter: + request_configuration = GroupsRequestBuilder.GroupsRequestBuilderGetRequestConfiguration( + query_parameters=GroupsRequestBuilder.GroupsRequestBuilderGetQueryParameters( + count=True, + filter=filter, + ), + ) + groups = await self._client.groups.get(request_configuration=request_configuration) + else: + groups = await self._client.groups.get() + + if groups and groups.value: + return groups.value + return [] + + async def get_group_members(self, group_id, filters=None): + request_configuration = TransitiveMembersRequestBuilder.TransitiveMembersRequestBuilderGetRequestConfiguration( + query_parameters=TransitiveMembersRequestBuilder.TransitiveMembersRequestBuilderGetQueryParameters( + count=True, + ), + ) + if filters: + request_configuration.query_parameters.filter = filters + return await self._client.groups.by_group_id(group_id).transitive_members.get( + request_configuration=request_configuration) + + async def add_group_member(self, group_id, obj_id): + request_body = ReferenceCreate( + odata_id="https://graph.microsoft.com/v1.0/directoryObjects/{0}".format(obj_id), + ) + await self._client.groups.by_group_id(group_id).members.ref.post(body=request_body) + + async def delete_group_member(self, group_id, member_id): + await self._client.groups.by_group_id(group_id).members.by_directory_object_id(member_id).ref.delete() + + async def get_group_owners(self, group_id): + request_configuration = GroupsRequestBuilder.GroupsRequestBuilderGetRequestConfiguration( + query_parameters=GroupsRequestBuilder.GroupsRequestBuilderGetQueryParameters( + count=True, + ), + ) + return await self._client.groups.by_group_id(group_id).owners.get(request_configuration=request_configuration) + + async def add_gropup_owner(self, group_id, obj_id): + request_body = ReferenceCreate( + odata_id="https://graph.microsoft.com/v1.0/users/{0}".format(obj_id), + ) + await self._client.groups.by_group_id(group_id).owners.ref.post(body=request_body) + + async def remove_gropup_owner(self, group_id, obj_id): + await self._client.groups.by_group_id(group_id).owners.by_directory_object_id(obj_id).ref.delete() + def main(): AzureRMADGroup() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup_info.py index 37bc1febb..3525bdf1b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adgroup_info.py @@ -1,10 +1,11 @@ #!/usr/bin/python # -# Copyright (c) 2021 Cole Neubauer, (@coleneubauer) +# Copyright (c) 2021 Cole Neubauer, (@coleneubauer), xuzhang3 (@xuzhang3) # # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function + __metaclass__ = type DOCUMENTATION = ''' @@ -14,11 +15,6 @@ short_description: Get Azure Active Directory group info description: - Get Azure Active Directory group info. options: - tenant: - description: - - The tenant ID. - type: str - required: True object_id: description: - The object id for the ad group. @@ -70,53 +66,46 @@ extends_documentation_fragment: - azure.azcollection.azure author: - Cole Neubauer(@coleneubauer) + - Xu Zhang(@xuzhang) ''' EXAMPLES = ''' - name: Return a specific group using object_id azure_rm_adgroup_info: object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Return a specific group using object_id and return the owners of the group azure_rm_adgroup_info: object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx return_owners: true - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Return a specific group using object_id and return the owners and members of the group azure_rm_adgroup_info: object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx return_owners: true return_group_members: true - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Return a specific group using object_id and return the groups the group is a member of azure_rm_adgroup_info: object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx return_member_groups: true - tenant: "{{ tenant_id }}" - name: Return a specific group using object_id and check an ID for membership azure_rm_adgroup_info: object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx check_membership: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Return a specific group using displayName for attribute_name azure_rm_adgroup_info: attribute_name: "displayName" attribute_value: "Display-Name-Of-AD-Group" - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Return groups matching odata_filter azure_rm_adgroup_info: odata_filter: "mailNickname eq 'Mail-Nickname-Of-AD-Group'" - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Return all groups azure_rm_adgroup_info: - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx all: true ''' @@ -167,13 +156,23 @@ group_members: - The members of the group. returned: always type: list +description: + description: + - An optional description for the group. + type: str + returned: always + sample: 'fortest' ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from azure.graphrbac.models import GraphErrorException - from azure.graphrbac.models import CheckGroupMembershipParameters + import asyncio + from msgraph.generated.groups.groups_request_builder import GroupsRequestBuilder + from msgraph.generated.groups.item.transitive_members.transitive_members_request_builder import \ + TransitiveMembersRequestBuilder + from msgraph.generated.groups.item.get_member_groups.get_member_groups_post_request_body import \ + GetMemberGroupsPostRequestBody except ImportError: # This is handled in azure_rm_common pass @@ -192,10 +191,8 @@ class AzureRMADGroupInfo(AzureRMModuleBase): return_group_members=dict(type='bool', default=False), return_member_groups=dict(type='bool', default=False), all=dict(type='bool', default=False), - tenant=dict(type='str', required=True), ) - self.tenant = None self.object_id = None self.attribute_name = None self.attribute_value = None @@ -207,6 +204,7 @@ class AzureRMADGroupInfo(AzureRMModuleBase): self.all = False self.results = dict(changed=False) + self._client = None mutually_exclusive = [['odata_filter', 'attribute_name', 'object_id', 'all']] required_together = [['attribute_name', 'attribute_value']] @@ -228,20 +226,19 @@ class AzureRMADGroupInfo(AzureRMModuleBase): ad_groups = [] try: - client = self.get_graphrbac_client(self.tenant) + self._client = self.get_msgraph_client() if self.object_id is not None: - ad_groups = [client.groups.get(self.object_id)] + ad_groups = [asyncio.get_event_loop().run_until_complete(self.get_group(self.object_id))] elif self.attribute_name is not None and self.attribute_value is not None: - ad_groups = list(client.groups.list(filter="{0} eq '{1}'".format(self.attribute_name, self.attribute_value))) + ad_groups = asyncio.get_event_loop().run_until_complete( + self.get_group_list(filter="{0} eq '{1}'".format(self.attribute_name, self.attribute_value))) elif self.odata_filter is not None: # run a filter based on user input - ad_groups = list(client.groups.list(filter=self.odata_filter)) + ad_groups = asyncio.get_event_loop().run_until_complete(self.get_group_list(filter=self.odata_filter)) elif self.all: - ad_groups = list(client.groups.list()) - - self.results['ad_groups'] = [self.set_results(group, client) for group in ad_groups] - - except GraphErrorException as e: + ad_groups = asyncio.get_event_loop().run_until_complete(self.get_group_list()) + self.results['ad_groups'] = [self.set_results(group) for group in ad_groups] + except Exception as e: self.fail("failed to get ad group info {0}".format(str(e))) return self.results @@ -256,24 +253,25 @@ class AzureRMADGroupInfo(AzureRMModuleBase): def serviceprincipal_to_dict(self, object): return dict( app_id=object.app_id, - object_id=object.object_id, + object_id=object.id, app_display_name=object.display_name, app_role_assignment_required=object.app_role_assignment_required ) def group_to_dict(self, object): return dict( - object_id=object.object_id, + object_id=object.id, display_name=object.display_name, mail_nickname=object.mail_nickname, mail_enabled=object.mail_enabled, security_enabled=object.security_enabled, - mail=object.mail + mail=object.mail, + description=object.description ) def user_to_dict(self, object): return dict( - object_id=object.object_id, + object_id=object.id, display_name=object.display_name, user_principal_name=object.user_principal_name, mail_nickname=object.mail_nickname, @@ -283,35 +281,94 @@ class AzureRMADGroupInfo(AzureRMModuleBase): ) def result_to_dict(self, object): - if object.object_type == "Group": + if object.odata_type == "#microsoft.graph.group": return self.group_to_dict(object) - elif object.object_type == "User": + elif object.odata_type == "#microsoft.graph.user": return self.user_to_dict(object) - elif object.object_type == "Application": + elif object.odata_type == "#microsoft.graph.application": return self.application_to_dict(object) - elif object.object_type == "ServicePrincipal": + elif object.odata_type == "#microsoft.graph.servicePrincipal": return self.serviceprincipal_to_dict(object) else: - return object.object_type + return object.odata_type - def set_results(self, object, client): + def set_results(self, object): results = self.group_to_dict(object) if results["object_id"] and self.return_owners: - results["group_owners"] = [self.result_to_dict(object) for object in list(client.groups.list_owners(results["object_id"]))] + ret = asyncio.get_event_loop().run_until_complete(self.get_group_owners(results["object_id"])) + results["group_owners"] = [self.result_to_dict(object) for object in ret.value] if results["object_id"] and self.return_group_members: - results["group_members"] = [self.result_to_dict(object) for object in list(client.groups.get_group_members(results["object_id"]))] + ret = asyncio.get_event_loop().run_until_complete(self.get_group_members(results["object_id"])) + results["group_members"] = [self.result_to_dict(object) for object in ret.value] if results["object_id"] and self.return_member_groups: - results["member_groups"] = [self.result_to_dict(object) for object in list(client.groups.get_member_groups(results["object_id"], False))] + ret = asyncio.get_event_loop().run_until_complete(self.get_member_groups(results["object_id"])) + results["member_groups"] = [self.result_to_dict(object) for object in list(ret.value)] if results["object_id"] and self.check_membership: - results["is_member_of"] = client.groups.is_member_of( - CheckGroupMembershipParameters(group_id=results["object_id"], member_id=self.check_membership)).value + filter = "id eq '{0}' ".format(self.check_membership) + ret = asyncio.get_event_loop().run_until_complete(self.get_group_members(results["object_id"], filter)) + results["is_member_of"] = True if ret.value and len(ret.value) != 0 else False return results + async def get_group(self, group_id): + return await self._client.groups.by_group_id(group_id).get() + + async def get_group_list(self, filter=None): + kwargs = {} + if filter: + request_configuration = GroupsRequestBuilder.GroupsRequestBuilderGetRequestConfiguration( + query_parameters=GroupsRequestBuilder.GroupsRequestBuilderGetQueryParameters( + count=True, + filter=filter, + ), + ) + kwargs["request_configuration"] = request_configuration + + groups = [] + # paginated response can be quite large + response = await self._client.groups.get(**kwargs) + if response: + groups += response.value + while response is not None and response.odata_next_link is not None: + response = await self._client.groups.with_url(response.odata_next_link).get(**kwargs) + if response: + groups += response.value + + return groups + + async def get_group_owners(self, group_id): + request_configuration = GroupsRequestBuilder.GroupsRequestBuilderGetRequestConfiguration( + query_parameters=GroupsRequestBuilder.GroupsRequestBuilderGetQueryParameters( + count=True, + select=['id', 'displayName', 'userPrincipalName', 'mailNickname', 'mail', 'accountEnabled', 'userType', + 'appId', 'appRoleAssignmentRequired'] + + ), + ) + return await self._client.groups.by_group_id(group_id).owners.get(request_configuration=request_configuration) + + async def get_group_members(self, group_id, filters=None): + request_configuration = TransitiveMembersRequestBuilder.TransitiveMembersRequestBuilderGetRequestConfiguration( + query_parameters=TransitiveMembersRequestBuilder.TransitiveMembersRequestBuilderGetQueryParameters( + count=True, + select=['id', 'displayName', 'userPrincipalName', 'mailNickname', 'mail', 'accountEnabled', 'userType', + 'appId', 'appRoleAssignmentRequired'] + + ), + ) + if filters: + request_configuration.query_parameters.filter = filters + return await self._client.groups.by_group_id(group_id).transitive_members.get( + request_configuration=request_configuration) + + async def get_member_groups(self, obj_id): + request_body = GetMemberGroupsPostRequestBody(security_enabled_only=False) + return await self._client.groups.by_group_id(obj_id).get_member_groups.post(body=request_body) + def main(): AzureRMADGroupInfo() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword.py index 587d842b5..c6a634db9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword.py @@ -32,21 +32,17 @@ options: key_id: description: - The password key ID. + - It isn't supported anymore in the create operation. See the Azure documentation for more information + U(https://learn.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0&tabs=http#request-body). type: str - tenant: - description: - - The tenant ID. - type: str - required: True end_date: description: - Date or datemtime after which credentials expire. - Default value is one year after current time. type: str - value: + display_name: description: - - The application password value. - - Length greater than 18 characters. + - The friendly name of the application password. type: str app_object_id: description: @@ -77,8 +73,7 @@ EXAMPLES = ''' azure_rm_adpassword: app_id: "{{ app_id }}" state: present - value: "$abc12345678" - tenant: "{{ tenant_id }}" + display_name: "Password friendly name" ''' RETURN = ''' @@ -102,17 +97,26 @@ start_date: type: str returned: always sample: "2020-06-28T06:00:32.637070+00:00" - +secret_text: + description: + - The application password value. + - API only returns the application password value at creation. + type: str + returned: created + sample: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase -import uuid import datetime try: - from azure.graphrbac.models import GraphErrorException - from azure.graphrbac.models import PasswordCredential - from azure.graphrbac.models import ApplicationUpdateParameters + import asyncio + from msgraph.generated.models.password_credential import PasswordCredential + from msgraph.generated.applications.item.add_password.add_password_post_request_body import \ + AddPasswordPostRequestBody + from msgraph.generated.applications.item.remove_password.remove_password_post_request_body import \ + RemovePasswordPostRequestBody + from msgraph.generated.applications.applications_request_builder import ApplicationsRequestBuilder from dateutil.relativedelta import relativedelta except ImportError: # This is handled in azure_rm_common @@ -127,19 +131,17 @@ class AzureRMADPassword(AzureRMModuleBase): service_principal_object_id=dict(type='str'), app_object_id=dict(type='str'), key_id=dict(type='str'), - tenant=dict(type='str', required=True), - value=dict(type='str'), + display_name=dict(type='str'), end_date=dict(type='str'), state=dict(type='str', default='present', choices=['present', 'absent']), ) self.state = None - self.tenant = None self.app_id = None self.service_principal_object_id = None self.app_object_id = None self.key_id = None - self.value = None + self.display_name = None self.end_date = None self.results = dict(changed=False) @@ -154,13 +156,13 @@ class AzureRMADPassword(AzureRMModuleBase): for key in list(self.module_arg_spec.keys()): setattr(self, key, kwargs[key]) - self.client = self.get_graphrbac_client(self.tenant) + self._client = self.get_msgraph_client() self.resolve_app_obj_id() passwords = self.get_all_passwords() if self.state == 'present': if self.key_id and self.key_exists(passwords): - self.update(passwords) + self.update_password(passwords) else: self.create_password(passwords) else: @@ -173,7 +175,7 @@ class AzureRMADPassword(AzureRMModuleBase): def key_exists(self, old_passwords): for pd in old_passwords: - if pd.key_id == self.key_id: + if str(pd.key_id) == self.key_id: return True return False @@ -183,27 +185,31 @@ class AzureRMADPassword(AzureRMModuleBase): return elif self.app_id or self.service_principal_object_id: if not self.app_id: - sp = self.client.service_principals.get(self.service_principal_object_id) + sp = asyncio.get_event_loop().run_until_complete(self.get_service_principal()) self.app_id = sp.app_id if not self.app_id: - self.fail("can't resolve app via service principal object id {0}".format(self.service_principal_object_id)) + self.fail("can't resolve app via service principal object id {0}".format( + self.service_principal_object_id)) - result = list(self.client.applications.list(filter="appId eq '{0}'".format(self.app_id))) + apps = asyncio.get_event_loop().run_until_complete(self.get_applications()) + result = list(apps.value) if result: - self.app_object_id = result[0].object_id + self.app_object_id = result[0].id else: self.fail("can't resolve app via app id {0}".format(self.app_id)) else: self.fail("one of the [app_id, app_object_id, service_principal_id] must be set") - except GraphErrorException as ge: + except Exception as ge: self.fail("error in resolve app_object_id {0}".format(str(ge))) def get_all_passwords(self): try: - return list(self.client.applications.list_password_credentials(self.app_object_id)) - except GraphErrorException as ge: + application = asyncio.get_event_loop().run_until_complete(self.get_application()) + passwordCredentials = application.password_credentials + return passwordCredentials + except Exception as ge: self.fail("failed to fetch passwords for app {0}: {1}".format(self.app_object_id, str(ge))) def delete_all_passwords(self, old_passwords): @@ -212,9 +218,10 @@ class AzureRMADPassword(AzureRMModuleBase): self.results['changed'] = False return try: - self.client.applications.patch(self.app_object_id, ApplicationUpdateParameters(password_credentials=[])) + for pd in old_passwords: + asyncio.get_event_loop().run_until_complete(self.remove_password(pd.key_id)) self.results['changed'] = True - except GraphErrorException as ge: + except Exception as ge: self.fail("fail to purge all passwords for app: {0} - {1}".format(self.app_object_id, str(ge))) def delete_password(self, old_passwords): @@ -225,46 +232,38 @@ class AzureRMADPassword(AzureRMModuleBase): num_of_passwords_before_delete = len(old_passwords) for pd in old_passwords: - if pd.key_id == self.key_id: - old_passwords.remove(pd) + if str(pd.key_id) == self.key_id: + try: + asyncio.get_event_loop().run_until_complete(self.remove_password(pd.key_id)) + + num_of_passwords_after_delete = len(self.get_all_passwords()) + if num_of_passwords_after_delete != num_of_passwords_before_delete: + self.results['changed'] = True + except Exception as ge: + self.fail("failed to delete password with key id {0} - {1}".format(self.app_id, str(ge))) break - try: - self.client.applications.patch(self.app_object_id, ApplicationUpdateParameters(password_credentials=old_passwords)) - num_of_passwords_after_delete = len(self.get_all_passwords()) - if num_of_passwords_after_delete != num_of_passwords_before_delete: - self.results['changed'] = True - - except GraphErrorException as ge: - self.fail("failed to delete password with key id {0} - {1}".format(self.app_id, str(ge))) def create_password(self, old_passwords): - - def gen_guid(): - return uuid.uuid4() - - if self.value is None: - self.fail("when creating a new password, module parameter value can't be None") - start_date = datetime.datetime.now(datetime.timezone.utc) end_date = self.end_date or start_date + relativedelta(years=1) - value = self.value - key_id = self.key_id or str(gen_guid()) - - new_password = PasswordCredential(start_date=start_date, end_date=end_date, key_id=key_id, - value=value, custom_key_identifier=None) - old_passwords.append(new_password) + display_name = self.display_name + num_of_passwords_before_add = len(old_passwords) try: - client = self.get_graphrbac_client(self.tenant) - app_patch_parameters = ApplicationUpdateParameters(password_credentials=old_passwords) - client.applications.patch(self.app_object_id, app_patch_parameters) - - new_passwords = self.get_all_passwords() - for pd in new_passwords: - if pd.key_id == key_id: - self.results['changed'] = True - self.results.update(self.to_dict(pd)) - except GraphErrorException as ge: + request_body = AddPasswordPostRequestBody( + password_credential=PasswordCredential( + start_date_time=start_date, + end_date_time=end_date, + display_name=display_name + ), + ) + pd = asyncio.get_event_loop().run_until_complete(self.add_password(request_body)) + + num_of_passwords_after_add = len(self.get_all_passwords()) + if num_of_passwords_after_add != num_of_passwords_before_add: + self.results['changed'] = True + self.results.update(self.to_dict(pd)) + except Exception as ge: self.fail("failed to create new password: {0}".format(str(ge))) def update_password(self, old_passwords): @@ -272,10 +271,36 @@ class AzureRMADPassword(AzureRMModuleBase): def to_dict(self, pd): return dict( - end_date=pd.end_date, - start_date=pd.start_date, - key_id=pd.key_id + end_date=str(pd.end_date_time), + start_date=str(pd.start_date_time), + key_id=str(pd.key_id), + secret_text=str(pd.secret_text) + ) + + async def get_service_principal(self): + return await self._client.service_principals.by_service_principal_id(self.service_principal_object_id).get() + + async def get_applications(self): + request_configuration = ApplicationsRequestBuilder.ApplicationsRequestBuilderGetRequestConfiguration( + query_parameters=ApplicationsRequestBuilder.ApplicationsRequestBuilderGetQueryParameters( + filter="appId eq '{0}'".format(self.app_id), + ), ) + return await self._client.applications.get(request_configuration=request_configuration) + + async def get_application(self): + return await self._client.applications.by_application_id(self.app_object_id).get() + + async def remove_password(self, key_id): + request_body = RemovePasswordPostRequestBody( + key_id=key_id, + ) + return await self._client.applications.by_application_id(self.app_object_id).remove_password.post( + body=request_body) + + async def add_password(self, request_body): + return await self._client.applications.by_application_id(self.app_object_id).add_password.post( + body=request_body) def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword_info.py index 7c82b7b9f..229ef100d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adpassword_info.py @@ -8,7 +8,6 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type - DOCUMENTATION = ''' module: azure_rm_adpassword_info @@ -32,11 +31,6 @@ options: description: - The password key ID. type: str - tenant: - description: - - The tenant ID. - type: str - required: True end_date: description: - Date or datemtime after which credentials expire. @@ -64,7 +58,6 @@ EXAMPLES = ''' - name: get ad password info azure_rm_adpassword_info: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" key_id: "{{ key_id }}" ''' @@ -107,7 +100,8 @@ passwords: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: - from azure.graphrbac.models import GraphErrorException + import asyncio + from msgraph.generated.applications.applications_request_builder import ApplicationsRequestBuilder except ImportError: # This is handled in azure_rm_common pass @@ -121,12 +115,10 @@ class AzureRMADPasswordInfo(AzureRMModuleBase): app_object_id=dict(type='str'), service_principal_object_id=dict(type='str'), key_id=dict(type='str'), - tenant=dict(type='str', required=True), value=dict(type='str'), end_date=dict(type='str'), ) - self.tenant = None self.app_id = None self.service_principal_object_id = None self.app_object_id = None @@ -147,12 +139,12 @@ class AzureRMADPasswordInfo(AzureRMModuleBase): for key in list(self.module_arg_spec.keys()): setattr(self, key, kwargs[key]) - self.client = self.get_graphrbac_client(self.tenant) + self._client = self.get_msgraph_client() self.resolve_app_obj_id() passwords = self.get_all_passwords() if self.key_id: - filtered = [pd for pd in passwords if pd.key_id == self.key_id] + filtered = [pd for pd in passwords if str(pd.key_id) == self.key_id] self.results['passwords'] = [self.to_dict(pd) for pd in filtered] else: self.results['passwords'] = [self.to_dict(pd) for pd in passwords] @@ -165,37 +157,55 @@ class AzureRMADPasswordInfo(AzureRMModuleBase): return elif self.app_id or self.service_principal_object_id: if not self.app_id: - sp = self.client.service_principals.get(self.service_principal_id) + sp = asyncio.get_event_loop().run_until_complete(self.get_service_principal()) self.app_id = sp.app_id if not self.app_id: - self.fail("can't resolve app via service principal object id {0}".format(self.service_principal_object_id)) + self.fail("can't resolve app via service principal object id {0}".format( + self.service_principal_object_id)) - result = list(self.client.applications.list(filter="appId eq '{0}'".format(self.app_id))) + apps = asyncio.get_event_loop().run_until_complete(self.get_applications()) + result = list(apps.value) if result: - self.app_object_id = result[0].object_id + self.app_object_id = result[0].id else: self.fail("can't resolve app via app id {0}".format(self.app_id)) else: - self.fail("one of the [app_id, app_object_id, service_principal_id] must be set") + self.fail("one of the [app_id, app_object_id, service_principal_object_id] must be set") - except GraphErrorException as ge: + except Exception as ge: self.fail("error in resolve app_object_id {0}".format(str(ge))) def get_all_passwords(self): try: - return list(self.client.applications.list_password_credentials(self.app_object_id)) - except GraphErrorException as ge: + application = asyncio.get_event_loop().run_until_complete(self.get_application()) + passwordCredentials = application.password_credentials + return passwordCredentials + except Exception as ge: self.fail("failed to fetch passwords for app {0}: {1}".format(self.app_object_id, str(ge))) def to_dict(self, pd): return dict( - end_date=pd.end_date, - start_date=pd.start_date, - key_id=pd.key_id, + end_date=pd.end_date_time, + start_date=pd.start_date_time, + key_id=str(pd.key_id), custom_key_identifier=str(pd.custom_key_identifier) ) + async def get_service_principal(self): + return await self._client.service_principals.by_service_principal_id(self.service_principal_object_id).get() + + async def get_applications(self): + request_configuration = ApplicationsRequestBuilder.ApplicationsRequestBuilderGetRequestConfiguration( + query_parameters=ApplicationsRequestBuilder.ApplicationsRequestBuilderGetQueryParameters( + filter="appId eq '{0}'".format(self.app_id), + ), + ) + return await self._client.applications.get(request_configuration=request_configuration) + + async def get_application(self): + return await self._client.applications.by_application_id(self.app_object_id).get() + def main(): AzureRMADPasswordInfo() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal.py index a7d3b39fd..ef12d642d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal.py @@ -5,8 +5,8 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function -__metaclass__ = type +__metaclass__ = type DOCUMENTATION = ''' --- @@ -25,11 +25,6 @@ options: - The application ID. type: str required: True - tenant: - description: - - The tenant ID. - type: str - required: True app_role_assignment_required: description: - Whether the Role of the Service Principal is set. @@ -57,7 +52,6 @@ EXAMPLES = ''' azure_rm_adserviceprincipal: app_id: "{{ app_id }}" state: present - tenant: "{{ tenant_id }}" ''' RETURN = ''' @@ -89,13 +83,15 @@ object_id: ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt + try: - from azure.graphrbac.models import ServicePrincipalCreateParameters + from msgraph.generated.models.service_principal import ServicePrincipal except Exception: pass try: - from azure.graphrbac.models import GraphErrorException + import asyncio + from msgraph.generated.service_principals.service_principals_request_builder import ServicePrincipalsRequestBuilder except ImportError: # This is handled in azure_rm_common pass @@ -106,13 +102,11 @@ class AzureRMADServicePrincipal(AzureRMModuleBaseExt): self.module_arg_spec = dict( app_id=dict(type='str', required=True), - tenant=dict(type='str', required=True), state=dict(type='str', default='present', choices=['present', 'absent']), app_role_assignment_required=dict(type='bool') ) self.state = None - self.tenant = None self.app_id = None self.app_role_assignment_required = None self.object_id = None @@ -128,6 +122,8 @@ class AzureRMADServicePrincipal(AzureRMModuleBaseExt): for key in list(self.module_arg_spec.keys()): setattr(self, key, kwargs[key]) + self._client = self.get_msgraph_client() + response = self.get_resource() if response: @@ -146,46 +142,47 @@ class AzureRMADServicePrincipal(AzureRMModuleBaseExt): def create_resource(self): try: - client = self.get_graphrbac_client(self.tenant) - response = client.service_principals.create(ServicePrincipalCreateParameters(app_id=self.app_id, account_enabled=True)) + response = asyncio.get_event_loop().run_until_complete(self.create_service_principal()) self.results['changed'] = True self.results.update(self.to_dict(response)) return response - except GraphErrorException as ge: + except Exception as ge: self.fail("Error creating service principle, app id {0} - {1}".format(self.app_id, str(ge))) def update_resource(self, old_response): try: - client = self.get_graphrbac_client(self.tenant) - to_update = {} + request_body = ServicePrincipal( + app_role_assignment_required=None, + ) if self.app_role_assignment_required is not None: - to_update['app_role_assignment_required'] = self.app_role_assignment_required + request_body = ServicePrincipal( + app_role_assignment_required=self.app_role_assignment_required + ) - client.service_principals.update(old_response['object_id'], to_update) + asyncio.get_event_loop().run_until_complete(self.update_service_principal(old_response, request_body)) self.results['changed'] = True self.results.update(self.get_resource()) - except GraphErrorException as ge: + except Exception as ge: self.fail("Error updating the service principal app_id {0} - {1}".format(self.app_id, str(ge))) def delete_resource(self, response): try: - client = self.get_graphrbac_client(self.tenant) - client.service_principals.delete(response.get('object_id')) + asyncio.get_event_loop().run_until_complete(self.delete_service_principal(response)) self.results['changed'] = True return True - except GraphErrorException as ge: + except Exception as ge: self.fail("Error deleting service principal app_id {0} - {1}".format(self.app_id, str(ge))) def get_resource(self): try: - client = self.get_graphrbac_client(self.tenant) - result = list(client.service_principals.list(filter="servicePrincipalNames/any(c:c eq '{0}')".format(self.app_id))) + sps = asyncio.get_event_loop().run_until_complete(self.get_service_principals()) + result = list(sps.value) if not result: return False result = result[0] return self.to_dict(result) - except GraphErrorException as ge: + except Exception as ge: self.log("Did not find the graph instance instance {0} - {1}".format(self.app_id, str(ge))) return False @@ -198,11 +195,33 @@ class AzureRMADServicePrincipal(AzureRMModuleBaseExt): def to_dict(self, object): return dict( app_id=object.app_id, - object_id=object.object_id, + object_id=object.id, app_display_name=object.display_name, app_role_assignment_required=object.app_role_assignment_required ) + async def create_service_principal(self): + request_body = ServicePrincipal( + app_id=self.app_id, + account_enabled=True + ) + return await self._client.service_principals.post(body=request_body) + + async def update_service_principal(self, old_response, request_body): + return await self._client.service_principals.by_service_principal_id(old_response['object_id']).patch( + body=request_body) + + async def delete_service_principal(self, response): + return await self._client.service_principals.by_service_principal_id(response.get('object_id')).delete() + + async def get_service_principals(self): + request_configuration = ServicePrincipalsRequestBuilder.ServicePrincipalsRequestBuilderGetRequestConfiguration( + query_parameters=ServicePrincipalsRequestBuilder.ServicePrincipalsRequestBuilderGetQueryParameters( + filter="servicePrincipalNames/any(c:c eq '{0}')".format(self.app_id), + ) + ) + return await self._client.service_principals.get(request_configuration=request_configuration) + def main(): AzureRMADServicePrincipal() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal_info.py index db27ccae8..d2acfac04 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_adserviceprincipal_info.py @@ -5,8 +5,8 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function -__metaclass__ = type +__metaclass__ = type DOCUMENTATION = ''' module: azure_rm_adserviceprincipal_info @@ -23,11 +23,6 @@ options: description: - The application ID. type: str - tenant: - description: - - The tenant ID. - type: str - required: True object_id: description: - It's service principal's object ID. @@ -45,34 +40,43 @@ EXAMPLES = ''' - name: get ad sp info azure_rm_adserviceprincipal_info: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" +- name: get all service principals + azure_rm_adserviceprincipal_info: ''' RETURN = ''' -app_display_name: - description: - - Object's display name or its prefix. - type: str - returned: always - sample: sp -app_id: +service_principals: description: - - The application ID. + - A list of service principals in the tenant. If app_id or object_id is set, the maximum length + of this list should be one. + type: list + elements: dict returned: always - type: str - sample: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -app_role_assignment_required: - description: - - Whether the Role of the Service Principal is set. - type: bool - returned: always - sample: false -object_id: - description: - - It's service principal's object ID. - returned: always - type: str - sample: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + contains: + app_display_name: + description: + - Object's display name or its prefix. + type: str + returned: always + sample: sp + app_id: + description: + - The application ID. + returned: always + type: str + sample: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + app_role_assignment_required: + description: + - Whether the Role of the Service Principal is set. + type: bool + returned: always + sample: false + object_id: + description: + - It's service principal's object ID. + returned: always + type: str + sample: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ''' @@ -80,7 +84,8 @@ object_id: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from azure.graphrbac.models import GraphErrorException + import asyncio + from msgraph.generated.service_principals.service_principals_request_builder import ServicePrincipalsRequestBuilder except ImportError: # This is handled in azure_rm_common pass @@ -92,10 +97,8 @@ class AzureRMADServicePrincipalInfo(AzureRMModuleBase): self.module_arg_spec = dict( app_id=dict(type='str'), object_id=dict(type='str'), - tenant=dict(type='str', required=True), ) - self.tenant = None self.app_id = None self.object_id = None self.results = dict(changed=False) @@ -110,17 +113,18 @@ class AzureRMADServicePrincipalInfo(AzureRMModuleBase): for key in list(self.module_arg_spec.keys()): setattr(self, key, kwargs[key]) + self._client = self.get_msgraph_client() + service_principals = [] try: - client = self.get_graphrbac_client(self.tenant) if self.object_id is None: - service_principals = list(client.service_principals.list(filter="servicePrincipalNames/any(c:c eq '{0}')".format(self.app_id))) + service_principals = asyncio.get_event_loop().run_until_complete(self.get_service_principals()) else: - service_principals = [client.service_principals.get(self.object_id)] + service_principals = [asyncio.get_event_loop().run_until_complete(self.get_service_principal())] self.results['service_principals'] = [self.to_dict(sp) for sp in service_principals] - except GraphErrorException as ge: + except Exception as ge: self.fail("failed to get service principal info {0}".format(str(ge))) return self.results @@ -128,11 +132,32 @@ class AzureRMADServicePrincipalInfo(AzureRMModuleBase): def to_dict(self, object): return dict( app_id=object.app_id, - object_id=object.object_id, + object_id=object.id, app_display_name=object.display_name, app_role_assignment_required=object.app_role_assignment_required ) + async def get_service_principal(self): + return await self._client.service_principals.by_service_principal_id(self.object_id).get() + + async def get_service_principals(self): + kwargs = {} + if self.app_id is not None: + request_configuration = ServicePrincipalsRequestBuilder.ServicePrincipalsRequestBuilderGetRequestConfiguration( + query_parameters=ServicePrincipalsRequestBuilder.ServicePrincipalsRequestBuilderGetQueryParameters( + filter="servicePrincipalNames/any(c:c eq '{0}')".format(self.app_id)) + ) + kwargs['request_configuration'] = request_configuration + service_principals = [] + response = await self._client.service_principals.get(**kwargs) + if response: + service_principals += response.value + while response is not None and response.odata_next_link is not None: + response = await self._client.service_principals.with_url(response.odata_next_link).get(**kwargs) + if response: + service_principals += response.value + return service_principals + def main(): AzureRMADServicePrincipalInfo() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser.py index b41c5ae7e..1e0a238c0 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser.py @@ -5,6 +5,7 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function + __metaclass__ = type DOCUMENTATION = ''' @@ -18,11 +19,6 @@ description: - Create, delete, and update an Azure Active Directory user. options: - tenant: - description: - - The tenant ID. - type: str - required: True state: description: - State of the ad user. Use C(present) to create or update an ad user and C(absent) to delete an ad user. @@ -57,11 +53,13 @@ options: - The surname for the user. - Used when either creating or updating a user account. type: str - immutable_id: + on_premises_immutable_id: description: - - The immutable_id of the user. + - The on_premises_immutable_id of the user. - Used when either creating or updating a user account. type: str + aliases: + - immutable_id mail: description: - The primary email address of the user. @@ -114,6 +112,13 @@ options: - Filter that can be used to specify a user to update or delete. - Mutually exclusive with I(object_id), I(attribute_name), and I(user_principal_name). type: str + company_name: + description: + - The name of the company that the user is associated with. + - This property can be useful for describing the company that an external user comes from. + - The maximum length is 64 characters.Returned only on $select. + - Supports $filter (eq, ne, not, ge, le, in, startsWith, and eq on null values). + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -126,30 +131,28 @@ EXAMPLES = ''' - name: Create user azure_rm_aduser: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" state: "present" account_enabled: "True" display_name: "Test_{{ user_principal_name }}_Display_Name" password_profile: "password" mail_nickname: "Test_{{ user_principal_name }}_mail_nickname" - immutable_id: "{{ object_id }}" + on_premises_immutable_id: "{{ object_id }}" given_name: "First" surname: "Last" user_type: "Member" usage_location: "US" mail: "{{ user_principal_name }}@contoso.com" + company_name: 'Test Company' - name: Update user with new value for account_enabled azure_rm_aduser: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" state: "present" account_enabled: "False" - name: Delete user azure_rm_aduser: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" state: "absent" ''' @@ -196,15 +199,21 @@ user_type: returned: always type: str sample: Member +company_name: + description: + - The name of the company that the user is associated with. + type: str + returned: always + sample: 'Test Company' ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from azure.graphrbac.models import UserUpdateParameters - from azure.graphrbac.models import UserCreateParameters - from azure.graphrbac.models import PasswordProfile - from azure.graphrbac.models import GraphErrorException + import asyncio + from msgraph.generated.models.password_profile import PasswordProfile + from msgraph.generated.models.user import User + from msgraph.generated.users.users_request_builder import UsersRequestBuilder except ImportError: # This is handled in azure_rm_common pass @@ -224,16 +233,15 @@ class AzureRMADUser(AzureRMModuleBase): display_name=dict(type='str'), password_profile=dict(type='str', no_log=True), mail_nickname=dict(type='str'), - immutable_id=dict(type='str'), + on_premises_immutable_id=dict(type='str', aliases=['immutable_id']), usage_location=dict(type='str'), given_name=dict(type='str'), surname=dict(type='str'), user_type=dict(type='str'), mail=dict(type='str'), - tenant=dict(type='str', required=True), + company_name=dict(type='str') ) - self.tenant = None self.user_principal_name = None self.state = None self.object_id = None @@ -244,12 +252,13 @@ class AzureRMADUser(AzureRMModuleBase): self.display_name = None self.password_profile = None self.mail_nickname = None - self.immutable_id = None + self.on_premises_immutable_id = None self.usage_location = None self.given_name = None self.surname = None self.user_type = None self.mail = None + self.company_name = None self.log_path = None self.log_mode = None @@ -273,9 +282,9 @@ class AzureRMADUser(AzureRMModuleBase): setattr(self, key, kwargs[key]) try: - client = self.get_graphrbac_client(self.tenant) + self._client = self.get_msgraph_client() - ad_user = self.get_exisiting_user(client) + ad_user = self.get_exisiting_user() if self.state == 'present': @@ -284,11 +293,13 @@ class AzureRMADUser(AzureRMModuleBase): password = None if self.password_profile: - password = PasswordProfile(password=self.password_profile) + password = PasswordProfile( + password=self.password_profile, + ) should_update = False - if self.immutable_id and ad_user.immutable_id != self.immutable_id: + if self.on_premises_immutable_id and ad_user.on_premises_immutable_id != self.on_premises_immutable_id: should_update = True if should_update or self.usage_location and ad_user.usage_location != self.usage_location: should_update = True @@ -308,84 +319,73 @@ class AzureRMADUser(AzureRMModuleBase): should_update = True if should_update or self.mail_nickname and ad_user.mail_nickname != self.mail_nickname: should_update = True + if should_update or self.company_name and ad_user.company_name != self.company_name: + should_update = True if should_update: - parameters = UserUpdateParameters(immutable_id=self.immutable_id, - usage_location=self.usage_location, - given_name=self.given_name, - surname=self.surname, - user_type=self.user_type, - account_enabled=self.account_enabled, - display_name=self.display_name, - password_profile=password, - user_principal_name=self.user_principal_name, - mail_nickname=self.mail_nickname) - - client.users.update(upn_or_object_id=ad_user.object_id, parameters=parameters) + asyncio.get_event_loop().run_until_complete(self.update_user(ad_user, password)) self.results['changed'] = True # Get the updated versions of the users to return # the update method, has no return value so it needs to be explicitely returned in a call - ad_user = self.get_exisiting_user(client) + ad_user = self.get_exisiting_user() else: self.results['changed'] = False else: # Create, changed - password = PasswordProfile(password=self.password_profile) - parameters = UserCreateParameters(account_enabled=self.account_enabled, - display_name=self.display_name, - password_profile=password, - user_principal_name=self.user_principal_name, - mail_nickname=self.mail_nickname, - immutable_id=self.immutable_id, - usage_location=self.usage_location, - given_name=self.given_name, - surname=self.surname, - user_type=self.user_type, - mail=self.mail) - ad_user = client.users.create(parameters=parameters) + asyncio.get_event_loop().run_until_complete(self.create_user()) self.results['changed'] = True + ad_user = self.get_exisiting_user() self.results['ad_user'] = self.to_dict(ad_user) elif self.state == 'absent': if ad_user: # Delete, changed - client.users.delete(ad_user.object_id) + asyncio.get_event_loop().run_until_complete(self.delete_user(ad_user)) self.results['changed'] = True else: # Do nothing unchanged self.results['changed'] = False - except GraphErrorException as e: + except Exception as e: self.fail("failed to get ad user info {0}".format(str(e))) return self.results - def get_exisiting_user(self, client): + def get_exisiting_user(self): ad_user = None try: if self.user_principal_name is not None: - ad_user = client.users.get(self.user_principal_name) + ad_user = asyncio.get_event_loop().run_until_complete(self.get_user(self.user_principal_name)) elif self.object_id is not None: - ad_user = client.users.get(self.object_id) + ad_user = asyncio.get_event_loop().run_until_complete(self.get_user(self.object_id)) elif self.attribute_name is not None and self.attribute_value is not None: try: - ad_user = list(client.users.list(filter="{0} eq '{1}'".format(self.attribute_name, self.attribute_value)))[0] - except GraphErrorException as e: + users = asyncio.get_event_loop().run_until_complete( + self.get_users_by_filter("{0} eq '{1}'".format(self.attribute_name, self.attribute_value))) + ad_users = list(users.value) + ad_user = ad_users[0] + except Exception as e: # the type doesn't get more specific. Could check the error message but no guarantees that message doesn't change in the future # more stable to try again assuming the first error came from the attribute being a list try: - ad_user = list(client.users.list(filter="{0}/any(c:c eq '{1}')".format(self.attribute_name, self.attribute_value)))[0] - except GraphErrorException as sub_e: + users = asyncio.get_event_loop().run_until_complete(self.get_users_by_filter( + "{0}/any(c:c eq '{1}')".format(self.attribute_name, self.attribute_value))) + ad_users = list(users.value) + ad_user = ad_users[0] + except Exception as sub_e: raise elif self.odata_filter is not None: # run a filter based on user input to return based on any given attribute/query - ad_user = list(client.users.list(filter=self.odata_filter))[0] - except GraphErrorException as e: + users = asyncio.get_event_loop().run_until_complete(self.get_users_by_filter(self.odata_filter)) + ad_users = list(users.value) + ad_user = ad_users[0] + except Exception as e: # User was not found err_msg = str(e) - if err_msg == "Resource '{0}' does not exist or one of its queried reference-property objects are not present.".format(self.user_principal_name): + if "Resource '{0}' does not exist or one of its queried reference-property objects are not present.".format( + self.user_principal_name) in err_msg: ad_user = None else: raise @@ -393,13 +393,75 @@ class AzureRMADUser(AzureRMModuleBase): def to_dict(self, object): return dict( - object_id=object.object_id, + object_id=object.id, display_name=object.display_name, user_principal_name=object.user_principal_name, mail_nickname=object.mail_nickname, mail=object.mail, account_enabled=object.account_enabled, - user_type=object.user_type + user_type=object.user_type, + company_name=object.company_name + ) + + async def update_user(self, ad_user, password): + request_body = User( + on_premises_immutable_id=self.on_premises_immutable_id, + usage_location=self.usage_location, + given_name=self.given_name, + surname=self.surname, + user_type=self.user_type, + account_enabled=self.account_enabled, + display_name=self.display_name, + password_profile=password, + user_principal_name=self.user_principal_name, + mail_nickname=self.mail_nickname, + company_name=self.company_name + ) + return await self._client.users.by_user_id(ad_user.id).patch(body=request_body) + + async def create_user(self): + password = PasswordProfile( + password=self.password_profile + ) + request_body = User( + account_enabled=self.account_enabled, + display_name=self.display_name, + password_profile=password, + user_principal_name=self.user_principal_name, + mail_nickname=self.mail_nickname, + on_premises_immutable_id=self.on_premises_immutable_id, + usage_location=self.usage_location, + given_name=self.given_name, + surname=self.surname, + user_type=self.user_type, + mail=self.mail, + company_name=self.company_name + ) + return await self._client.users.post(body=request_body) + + async def delete_user(self, ad_user): + return await self._client.users.by_user_id(ad_user.id).delete() + + async def get_user(self, object): + request_configuration = UsersRequestBuilder.UsersRequestBuilderGetRequestConfiguration( + query_parameters=UsersRequestBuilder.UsersRequestBuilderGetQueryParameters( + select=["accountEnabled", "displayName", "mail", "mailNickname", "id", "userPrincipalName", "userType", + "onPremisesImmutableId", "usageLocation", "givenName", "surname", "companyName"] + ), + ) + return await self._client.users.by_user_id(object).get(request_configuration=request_configuration) + + async def get_users_by_filter(self, filter): + return await self._client.users.get( + request_configuration=UsersRequestBuilder.UsersRequestBuilderGetRequestConfiguration( + query_parameters=UsersRequestBuilder.UsersRequestBuilderGetQueryParameters( + filter=filter, + select=["accountEnabled", "displayName", "mail", "mailNickname", "id", "userPrincipalName", + "userType", "onPremisesImmutableId", "usageLocation", "givenName", "surname", "companyName"], + count=True + ), + headers={'ConsistencyLevel': "eventual", } + ) ) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser_info.py index 85460e741..98c30be57 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aduser_info.py @@ -5,6 +5,7 @@ # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function + __metaclass__ = type DOCUMENTATION = ''' @@ -18,11 +19,6 @@ description: - Get Azure Active Directory user info. options: - tenant: - description: - - The tenant ID. - type: str - required: True object_id: description: - The object id for the user. @@ -74,34 +70,28 @@ EXAMPLES = ''' - name: Using user_principal_name azure.azcollection.azure_rm_aduser_info: user_principal_name: user@contoso.com - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Using object_id azure.azcollection.azure_rm_aduser_info: object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Using attribute mailNickname - not a collection azure.azcollection.azure_rm_aduser_info: attribute_name: mailNickname attribute_value: users_mailNickname - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Using attribute proxyAddresses - a collection azure.azcollection.azure_rm_aduser_info: attribute_name: proxyAddresses attribute_value: SMTP:user@contoso.com - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Using Filter mailNickname azure.azcollection.azure_rm_aduser_info: odata_filter: mailNickname eq 'user@contoso.com' - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - name: Using Filter proxyAddresses azure.azcollection.azure_rm_aduser_info: odata_filter: proxyAddresses/any(c:c eq 'SMTP:user@contoso.com') - tenant: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ''' RETURN = ''' @@ -147,12 +137,19 @@ user_type: returned: always type: str sample: Member +company_name: + description: + - The name of the company that the user is associated with. + type: str + returned: always + sample: "Test Company" ''' from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBase try: - from azure.graphrbac.models import GraphErrorException + import asyncio + from msgraph.generated.users.users_request_builder import UsersRequestBuilder except ImportError: # This is handled in azure_rm_common pass @@ -168,10 +165,8 @@ class AzureRMADUserInfo(AzureRMModuleBase): attribute_value=dict(type='str'), odata_filter=dict(type='str'), all=dict(type='bool'), - tenant=dict(type='str', required=True), ) - self.tenant = None self.user_principal_name = None self.object_id = None self.attribute_name = None @@ -203,44 +198,88 @@ class AzureRMADUserInfo(AzureRMModuleBase): ad_users = [] try: - client = self.get_graphrbac_client(self.tenant) + self._client = self.get_msgraph_client() if self.user_principal_name is not None: - ad_users = [client.users.get(self.user_principal_name)] + ad_users = [asyncio.get_event_loop().run_until_complete(self.get_user(self.user_principal_name))] elif self.object_id is not None: - ad_users = [client.users.get(self.object_id)] + ad_users = [asyncio.get_event_loop().run_until_complete(self.get_user(self.object_id))] elif self.attribute_name is not None and self.attribute_value is not None: try: - ad_users = list(client.users.list(filter="{0} eq '{1}'".format(self.attribute_name, self.attribute_value))) - except GraphErrorException as e: + users = asyncio.get_event_loop().run_until_complete( + self.get_users_by_filter("{0} eq '{1}'".format(self.attribute_name, self.attribute_value))) + ad_users = list(users.value) + except Exception as e: # the type doesn't get more specific. Could check the error message but no guarantees that message doesn't change in the future # more stable to try again assuming the first error came from the attribute being a list try: - ad_users = list(client.users.list(filter="{0}/any(c:c eq '{1}')".format(self.attribute_name, self.attribute_value))) - except GraphErrorException as sub_e: + users = asyncio.get_event_loop().run_until_complete(self.get_users_by_filter( + "{0}/any(c:c eq '{1}')".format(self.attribute_name, self.attribute_value))) + ad_users = list(users.value) + except Exception as sub_e: raise elif self.odata_filter is not None: # run a filter based on user input to return based on any given attribute/query - ad_users = list(client.users.list(filter=self.odata_filter)) + users = asyncio.get_event_loop().run_until_complete(self.get_users_by_filter(self.odata_filter)) + ad_users = list(users.value) elif self.all: - ad_users = list(client.users.list()) + # this returns as a list, since we parse multiple pages + ad_users = asyncio.get_event_loop().run_until_complete(self.get_users()) self.results['ad_users'] = [self.to_dict(user) for user in ad_users] - except GraphErrorException as e: + except Exception as e: self.fail("failed to get ad user info {0}".format(str(e))) return self.results def to_dict(self, object): return dict( - object_id=object.object_id, + object_id=object.id, display_name=object.display_name, user_principal_name=object.user_principal_name, mail_nickname=object.mail_nickname, mail=object.mail, account_enabled=object.account_enabled, - user_type=object.user_type + user_type=object.user_type, + company_name=object.company_name + ) + + async def get_user(self, object): + request_configuration = UsersRequestBuilder.UsersRequestBuilderGetRequestConfiguration( + query_parameters=UsersRequestBuilder.UsersRequestBuilderGetQueryParameters( + select=["accountEnabled", "displayName", "mail", "mailNickname", "id", "userPrincipalName", "userType", "companyName"] + ), + ) + return await self._client.users.by_user_id(object).get(request_configuration=request_configuration) + + async def get_users(self): + request_configuration = UsersRequestBuilder.UsersRequestBuilderGetRequestConfiguration( + query_parameters=UsersRequestBuilder.UsersRequestBuilderGetQueryParameters( + select=["accountEnabled", "displayName", "mail", "mailNickname", "id", "userPrincipalName", "userType", "companyName"] + ), ) + users = [] + # paginated response can be quite large + response = await self._client.users.get(request_configuration=request_configuration) + if response: + users += response.value + while response is not None and response.odata_next_link is not None: + response = await self._client.users.with_url(response.odata_next_link).get(request_configuration=request_configuration) + if response: + users += response.value + + return users + + async def get_users_by_filter(self, filter): + return await self._client.users.get( + request_configuration=UsersRequestBuilder.UsersRequestBuilderGetRequestConfiguration( + query_parameters=UsersRequestBuilder.UsersRequestBuilderGetQueryParameters( + filter=filter, + select=["accountEnabled", "displayName", "mail", "mailNickname", "id", "userPrincipalName", + "userType", "companyName"], + count=True + ), + )) def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks.py index bb034b48b..0fb5095fe 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks.py @@ -284,7 +284,7 @@ options: type: str managed: description: - - Whether to enable manged AAD. + - Whether to enable managed AAD. type: bool default: false admin_group_object_ids: @@ -356,6 +356,57 @@ options: - Name of the resource group containing agent pool nodes. - Unable to update. type: str + pod_identity_profile: + description: + - Config pod identities in managed Kubernetes cluster. + type: dict + suboptions: + enabled: + description: + - Whether the pod identity addon is enabled. + type: bool + allow_network_plugin_kubenet: + description: + - Whether using Kubenet network plugin with AAD Pod Identity. + type: bool + user_assigned_identities: + description: + - The pod identities to use in the cluster. + type: list + elements: dict + suboptions: + name: + description: + - The name of the pod identity. + type: str + required: true + namespace: + description: + - The namespace of the pod identity. + type: str + required: true + binding_selector: + description: + - The binding selector to use for the AzureIdentityBinding resource. + type: str + identity: + description: + - The user assigned identity details. + type: dict + required: true + suboptions: + resource_id: + description: + - The resource ID of the user assigned identity. + type: str + object_id: + description: + - The object ID of the user assigned identity. + type: str + client_id: + description: + - The client ID of the user assigned identity. + type: str extends_documentation_fragment: - azure.azcollection.azure @@ -463,6 +514,45 @@ EXAMPLES = ''' type: VirtualMachineScaleSets enable_auto_scaling: false +- name: Create an AKS instance wit pod_identity_profile settings + azure_rm_aks: + name: "aks{{ rpfx }}" + resource_group: "{{ resource_group }}" + location: eastus + dns_prefix: "aks{{ rpfx }}" + kubernetes_version: "{{ versions.azure_aks_versions[0] }}" + service_principal: + client_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + client_secret: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + linux_profile: + admin_username: azureuser + ssh_key: ssh-rsa AAAAB3Ip6*************** + agent_pool_profiles: + - name: default + count: 1 + vm_size: Standard_B2s + type: VirtualMachineScaleSets + mode: System + node_labels: {"release":"stable"} + max_pods: 42 + availability_zones: + - 1 + - 2 + node_resource_group: "node{{ noderpfx }}" + enable_rbac: true + network_profile: + load_balancer_sku: standard + pod_identity_profile: + enabled: false + allow_network_plugin_kubenet: false + user_assigned_identities: + - name: fredtest + namespace: fredtest + binding_selector: test + identity: + client_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + object_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + - name: Remove a managed Azure Container Services (AKS) instance azure_rm_aks: name: myAKS @@ -490,7 +580,7 @@ state: changed: false dns_prefix: aks9860bdcd89 id: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroup/providers/Microsoft.ContainerService/managedClusters/aks9860bdc" - kube_config: "......" + kube_config: ["......"] kubernetes_version: 1.14.6 linux_profile: admin_username: azureuser @@ -500,13 +590,29 @@ state: provisioning_state: Succeeded service_principal_profile: client_id: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + pod_identity_profile: { + "allow_network_plugin_kubenet": false, + "user_assigned_identities": [ + { + "binding_selector": "test", + "identity": { + "client_id": xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, + "object_id": xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + }, + "name": "fredtest", + "namespace": "fredtest", + "provisioning_state": "Updating" + } + ] + } tags: {} type: Microsoft.ContainerService/ManagedClusters ''' -from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt try: from azure.core.exceptions import ResourceNotFoundError + from azure.core.exceptions import HttpResponseError except ImportError: # This is handled in azure_rm_common pass @@ -540,10 +646,19 @@ def create_aks_dict(aks): api_server_access_profile=create_api_server_access_profile_dict(aks.api_server_access_profile), addon=create_addon_dict(aks.addon_profiles), fqdn=aks.fqdn, - node_resource_group=aks.node_resource_group + node_resource_group=aks.node_resource_group, + pod_identity_profile=create_pod_identity_profile(aks.pod_identity_profile.as_dict()) if aks.pod_identity_profile else None ) +def create_pod_identity_profile(pod_profile): + return dict( + enabled=pod_profile.get('enabled', False), + allow_network_plugin_kubenet=pod_profile.get('allow_network_plugin_kubenet', False), + user_assigned_identities=pod_profile.get('user_assigned_identities') + ) if pod_profile else {} + + def create_network_profiles_dict(network): return dict( network_plugin=network.network_plugin, @@ -715,7 +830,7 @@ api_server_access_profile_spec = dict( ) -class AzureRMManagedCluster(AzureRMModuleBase): +class AzureRMManagedCluster(AzureRMModuleBaseExt): """Configuration class for an Azure RM container service (AKS) resource""" def __init__(self): @@ -777,6 +892,31 @@ class AzureRMManagedCluster(AzureRMModuleBase): ), node_resource_group=dict( type='str' + ), + pod_identity_profile=dict( + type='dict', + options=dict( + enabled=dict(type='bool'), + allow_network_plugin_kubenet=dict(type='bool'), + user_assigned_identities=dict( + type='list', + elements='dict', + options=dict( + name=dict(type='str', required=True), + namespace=dict(type='str', required=True), + binding_selector=dict(type='str'), + identity=dict( + type='dict', + required=True, + options=dict( + resource_id=dict(type='str'), + client_id=dict(type='str'), + object_id=dict(type='str') + ) + ) + ) + ) + ) ) ) @@ -796,6 +936,7 @@ class AzureRMManagedCluster(AzureRMModuleBase): self.api_server_access_profile = None self.addon = None self.node_resource_group = None + self.pod_identity_profile = None required_if = [ ('state', 'present', [ @@ -972,6 +1113,10 @@ class AzureRMManagedCluster(AzureRMModuleBase): if not matched: self.log("Agent Pool not found") to_be_updated = True + if not self.default_compare({}, self.pod_identity_profile, response['pod_identity_profile'], '', dict(compare=[])): + to_be_updated = True + else: + self.pod_identity_profile = response['pod_identity_profile'] if update_agentpool: self.log("Need to update agentpool") @@ -1044,6 +1189,15 @@ class AzureRMManagedCluster(AzureRMModuleBase): else: linux_profile = None + if self.pod_identity_profile: + pod_identity_profile = self.managedcluster_models.ManagedClusterPodIdentityProfile( + enabled=self.pod_identity_profile.get('enabled'), + allow_network_plugin_kubenet=self.pod_identity_profile.get('allow_network_plugin_kubenet'), + user_assigned_identities=self.pod_identity_profile.get('user_assigned_identities') + ) + else: + pod_identity_profile = None + parameters = self.managedcluster_models.ManagedCluster( location=self.location, dns_prefix=self.dns_prefix, @@ -1058,7 +1212,8 @@ class AzureRMManagedCluster(AzureRMModuleBase): aad_profile=self.create_aad_profile_instance(self.aad_profile), api_server_access_profile=self.create_api_server_access_profile_instance(self.api_server_access_profile), addon_profiles=self.create_addon_profile_instance(self.addon), - node_resource_group=self.node_resource_group + node_resource_group=self.node_resource_group, + pod_identity_profile=pod_identity_profile ) # self.log("service_principal_profile : {0}".format(parameters.service_principal_profile)) @@ -1169,10 +1324,12 @@ class AzureRMManagedCluster(AzureRMModuleBase): :return: AKS instance kubeconfig ''' - access_profile = self.managedcluster_client.managed_clusters.get_access_profile(resource_group_name=self.resource_group, - resource_name=self.name, - role_name="clusterUser") - return access_profile.kube_config.decode('utf-8') + try: + access_profile = self.managedcluster_client.managed_clusters.list_cluster_user_credentials(self.resource_group, self.name) + except HttpResponseError as ec: + self.log("Lists the cluster user credentials of a managed cluster Failed, Exception as {0}".format(ec)) + return [] + return [item.value.decode('utf-8') for item in access_profile.kubeconfigs] def create_agent_pool_profile_instance(self, agentpoolprofile): ''' diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks_info.py index c97bd893e..2e4fd7a26 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aks_info.py @@ -37,10 +37,14 @@ options: description: - Show kubeconfig of the AKS cluster. - Note the operation will cost more network overhead, not recommended when listing AKS. + - I(show_kubeconfig=monitoring) to lists the cluster monitoring user credentials of a managed cluster. + - I(show_kubeconfig=admin) to lists the cluster admin credentials of a managed cluster. + - I(show_kubeconfig=user) to lists the cluster user credentials of a managed cluster. type: str choices: - user - admin + - monitoring extends_documentation_fragment: - azure.azcollection.azure @@ -75,6 +79,7 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.core.exceptions import ResourceNotFoundError + from azure.core.exceptions import HttpResponseError except Exception: # handled in azure_rm_common pass @@ -91,7 +96,7 @@ class AzureRMManagedClusterInfo(AzureRMModuleBase): name=dict(type='str'), resource_group=dict(type='str'), tags=dict(type='list', elements='str'), - show_kubeconfig=dict(type='str', choices=['user', 'admin']), + show_kubeconfig=dict(type='str', choices=['user', 'admin', 'monitoring']), ) self.results = dict( @@ -196,11 +201,29 @@ class AzureRMManagedClusterInfo(AzureRMModuleBase): :return: AKS instance kubeconfig ''' - if not self.show_kubeconfig: - return '' - role_name = 'cluster{0}'.format(str.capitalize(self.show_kubeconfig)) - access_profile = self.managedcluster_client.managed_clusters.get_access_profile(resource_group, name, role_name) - return access_profile.kube_config.decode('utf-8') + if self.show_kubeconfig == 'user': + try: + access_profile = self.managedcluster_client.managed_clusters.list_cluster_user_credentials(self.resource_group, self.name) + except HttpResponseError as ec: + self.log("Lists the cluster user credentials of a managed cluster Failed, Exception as {0}".format(ec)) + return [] + return [item.value.decode('utf-8') for item in access_profile.kubeconfigs] + elif self.show_kubeconfig == 'admin': + try: + access_profile = self.managedcluster_client.managed_clusters.list_cluster_admin_credentials(self.resource_group, self.name) + except HttpResponseError as ec: + self.log("Lists the cluster admin credentials of a managed cluster Failed, Exception as {0}".format(ec)) + return [] + return [item.value.decode('utf-8') for item in access_profile.kubeconfigs] + elif self.show_kubeconfig == 'monitoring': + try: + access_profile = self.managedcluster_client.managed_clusters.list_cluster_monitoring_user_credentials(self.resource_group, self.name) + except HttpResponseError as ec: + self.log("Lists the cluster monitoring credentials of a managed cluster Failed, Exception as {0}".format(ec)) + return [] + return [item.value.decode('utf-8') for item in access_profile.kubeconfigs] + else: + return [] def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_akscredentials_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_akscredentials_info.py new file mode 100644 index 000000000..95a7fb104 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_akscredentials_info.py @@ -0,0 +1,209 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_akscredentials_info + +version_added: "2.3.0" + +short_description: List Azure Kubernetes Service Credentials facts + +description: + - List Azure Kubernetes Service Credentials facts. + +options: + cluster_name: + description: + - Azure Kubernetes Service or all Azure Kubernetes Services. + type: str + required: true + resource_group: + description: + - The resource group to search for the desired Azure Kubernetes Service. + type: str + required: true + show_admin_credentials: + description: + - Whether list Cluster Admin Credentials. + type: bool + default: false + show_user_credentials: + description: + - Whether list Cluster User Credentials. + type: bool + default: false + show_monitor_credentials: + description: + - Whether list Cluster Monitoring User Credentials. + type: bool + default: false + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - xuzhang3 (@xuzhang3) + - Fred Sun (@Fred-sun) +''' + +EXAMPLES = ''' +- name: Get managecluster admin credentials + azure_rm_akscredentials_info: + resource_group: "{{ resource_group }}" + cluster_name: cluter_name + show_admin_credentials: true + +- name: Get managecluster user credentials + azure_rm_akscredentials_info: + resource_group: "{{ resource_group }}" + cluster_name: cluster_name + show_user_credentials: true + +- name: Get managecluster monitor user credentials + azure_rm_akscredentials_info: + resource_group: "{{ resource_group }}" + cluster_name: cluster_name + show_monitor_credentials: true +''' + +RETURN = ''' +cluster_credentials: + description: + - Lists the cluster user, admin or monitoring user credentials of a managed cluster + returned: always + type: complex + contains: + cluster_name: + description: + - Azure Kubernetes Service or all Azure Kubernetes Services. + type: str + returned: always + sample: testcluster01 + resource_group: + description: + - The resource group to search for the desired Azure Kubernetes Service. + type: str + returned: always + sample: + name: + description: + - The name of the credential. + type: str + returned: always + sample: + value: + description: + - Base64-encoded Kubernetes configuration file. + type: str + returned: always + sample: "apiVersion: ************************" +''' + +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + +try: + from azure.core.exceptions import HttpResponseError +except Exception: + # handled in azure_rm_common + pass + +AZURE_OBJECT_CLASS = 'managedClustersCredentials' + + +class AzureRMAksCredentialsInfo(AzureRMModuleBase): + """Utility class to get Azure Kubernetes Service Credentials facts""" + + def __init__(self): + + self.module_args = dict( + cluster_name=dict(type='str', required=True), + resource_group=dict(type='str', required=True), + show_admin_credentials=dict(type='bool', default=False), + show_user_credentials=dict(type='bool', default=False), + show_monitor_credentials=dict(type='bool', default=False), + ) + + self.results = dict( + changed=False, + cluster_credentials=[], + ) + + mutually_exclusive = [('show_admin_credentials', 'show_user_credentials', 'show_monitor_credentials')] + + super(AzureRMAksCredentialsInfo, self).__init__( + derived_arg_spec=self.module_args, + supports_check_mode=True, + supports_tags=False, + mutually_exclusive=mutually_exclusive, + facts_module=True + ) + + def exec_module(self, **kwargs): + + for key in self.module_args: + setattr(self, key, kwargs[key]) + + if self.show_user_credentials: + self.results['cluster_credentials'] = self.get_user_credentials() + elif self.show_admin_credentials: + self.results['cluster_credentials'] = self.get_admin_credentials() + elif self.show_monitor_credentials: + self.results['cluster_credentials'] = self.get_monitor_credentials() + + self.results['resource_group'] = self.resource_group + self.results['cluster_name'] = self.cluster_name + return self.results + + def get_user_credentials(self): + """Get The Azure Kubernetes Service USER Credentials""" + response = None + + try: + response = self.managedcluster_client.managed_clusters.list_cluster_user_credentials(self.resource_group, self.cluster_name) + except HttpResponseError as ec: + self.fail("Lists the cluster user credentials of a managed cluster Failed, Exception as {0}".format(ec)) + return [self.format_response(item) for item in response.kubeconfigs] + + def get_admin_credentials(self): + """Get The Azure Kubernetes Service Admin Credentials""" + response = None + + try: + response = self.managedcluster_client.managed_clusters.list_cluster_admin_credentials(self.resource_group, self.cluster_name) + except HttpResponseError as ec: + self.fail("Lists the cluster admin credentials of a managed cluster Failed, Exception as {0}".format(ec)) + + return [self.format_response(item) for item in response.kubeconfigs] + + def get_monitor_credentials(self): + """Get The Azure Kubernetes Service Monitor Credentials""" + response = None + + try: + response = self.managedcluster_client.managed_clusters.list_cluster_monitoring_user_credentials(self.resource_group, self.cluster_name) + except HttpResponseError as ec: + self.fail("Lists the cluster monitoring credentials of a managed cluster Failed, Exception as {0}".format(ec)) + return [self.format_response(item) for item in response.kubeconfigs] + + def format_response(self, item): + if not item: + return + return dict(name=item.name, value=item.value.decode('utf-8')) + + +def main(): + """Main module execution code path""" + + AzureRMAksCredentialsInfo() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksversion_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksversion_info.py index 9e5af42ce..5d4f695a6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksversion_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_aksversion_info.py @@ -29,6 +29,13 @@ options: description: - Get the upgrade versions available for a managed Kubernetes cluster version. type: str + allow_preview: + description: + - Whether Kubernetes version is currently in preview. + - If I(allow_preview=True), returns the current preview status of the current Kubernetes version. + - If I(allow_preview=False), returns the Kubernetes version in a non-current preview state. + - If no set C(allow_preview), returns all the avaiable Kubernetes version. + type: bool extends_documentation_fragment: - azure.azcollection.azure @@ -38,6 +45,10 @@ author: ''' EXAMPLES = ''' +- name: Get current preview versions for AKS in location eastus + azure_rm_aksversion_info: + location: eastus + allow_preview: true - name: Get available versions for AKS in location eastus azure_rm_aksversion_info: location: eastus @@ -63,7 +74,8 @@ class AzureRMAKSVersion(AzureRMModuleBase): self.module_args = dict( location=dict(type='str', required=True), - version=dict(type='str') + version=dict(type='str'), + allow_preview=dict(type='bool') ) self.results = dict( @@ -73,6 +85,7 @@ class AzureRMAKSVersion(AzureRMModuleBase): self.location = None self.version = None + self.allow_preview = None super(AzureRMAKSVersion, self).__init__( derived_arg_spec=self.module_args, @@ -104,7 +117,14 @@ class AzureRMAKSVersion(AzureRMModuleBase): response = self.containerservice_client.container_services.list_orchestrators(self.location, resource_type='managedClusters') orchestrators = response.orchestrators for item in orchestrators: - result[item.orchestrator_version] = [x.orchestrator_version for x in item.upgrades] if item.upgrades else [] + if self.allow_preview is None: + result[item.orchestrator_version] = [x.orchestrator_version for x in item.upgrades] if item.upgrades else [] + elif self.allow_preview: + if item.is_preview: + result[item.orchestrator_version] = [x.orchestrator_version for x in item.upgrades] if item.upgrades else [] + else: + if not item.is_preview: + result[item.orchestrator_version] = [x.orchestrator_version for x in item.upgrades] if item.upgrades else [] if version: return result.get(version) or [] else: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement.py index 97a7868d1..4e7e359bb 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement.py @@ -296,41 +296,30 @@ class AzureApiManagement(AzureRMModuleBaseExt): self.module_arg_spec = dict( resource_group=dict( type='str', - updatable=False, - disposition='resourceGroupName', required=True ), service_name=dict( type='str', - updatable=False, - disposition='serviceName', required=True ), api_id=dict( type='str', - updatable=False, - disposition='apiId', required=True ), description=dict( type='str', - disposition='/properties/description' ), authentication_settings=dict( type='dict', - disposition='/properties/authenticationSettings', options=dict( o_auth2=dict( type='dict', - disposition='oAuth2', options=dict( authorization_server_id=dict( type='str', - disposition='authorizationServerId' ), scope=dict( type='str', - disposition='scope' ) ) ), @@ -339,12 +328,10 @@ class AzureApiManagement(AzureRMModuleBaseExt): options=dict( openid_provider_id=dict( type='str', - disposition='openidProviderId' ), bearer_token_sending_methods=dict( type='list', elements='str', - disposition='bearerTokenSendingMethods', choices=['authorizationHeader', 'query'] ) ) @@ -354,7 +341,6 @@ class AzureApiManagement(AzureRMModuleBaseExt): subscription_key_parameter_names=dict( type='dict', no_log=True, - disposition='/properties/subscriptionKeyParameterNames', options=dict( header=dict( type='str', @@ -368,63 +354,49 @@ class AzureApiManagement(AzureRMModuleBaseExt): ), type=dict( type='str', - disposition='/properties/type', choices=['http', 'soap'] ), api_revision=dict( type='str', - disposition='/properties/apiRevision' ), api_version=dict( type='str', - disposition='/properties/apiVersion' ), is_current=dict( type='bool', - disposition='/properties/isCurrent' ), api_revision_description=dict( type='str', - disposition='/properties/apiRevisionDescription' ), api_version_description=dict( type='str', - disposition='/properties/apiVersionDescription' ), api_version_set_id=dict( type='str', - disposition='/properties/apiVersionSetId', ), subscription_required=dict( type='bool', - disposition='/properties/subscriptionRequired' ), source_api_id=dict( type='str', - disposition='/properties/sourceApiId', ), display_name=dict( type='str', - disposition='/properties/displayName' ), service_url=dict( type='str', - disposition='/properties/serviceUrl' ), path=dict( type='str', - disposition='/properties/*', ), protocols=dict( type='list', elements='str', - disposition='/properties/protocols', choices=['http', 'https'] ), api_version_set=dict( type='dict', - disposition='/properties/apiVersionSet', options=dict( id=dict( type='str' @@ -437,28 +409,23 @@ class AzureApiManagement(AzureRMModuleBaseExt): ), versioning_scheme=dict( type='str', - disposition='versioningScheme', choices=['Segment', 'Query', 'Header'] ), version_query_name=dict( type='str', - disposition='versionQueryName' ), version_header_name=dict( type='str', - disposition='versionHeaderName' ) ) ), value=dict( type='str', - disposition='/properties/*' ), format=dict( type='str', - disposition='/properties/*', choices=['wadl-xml', 'wadl-link-json', 'swagger-json', @@ -471,21 +438,17 @@ class AzureApiManagement(AzureRMModuleBaseExt): ), wsdl_selector=dict( type='dict', - disposition='/properties/wsdlSelector', options=dict( wsdl_service_name=dict( type='str', - disposition='wsdlServiceName' ), wsdl_endpoint_name=dict( type='str', - disposition='wsdlEndpointName' ) ) ), api_type=dict( type='str', - disposition='/properties/apiType', choices=['http', 'soap'] ), state=dict( @@ -507,8 +470,9 @@ class AzureApiManagement(AzureRMModuleBaseExt): self.to_do = Actions.NoAction self.body = {} + self.body['properties'] = {} self.query_parameters = {} - self.query_parameters['api-version'] = '2020-06-01-preview' + self.query_parameters['api-version'] = '2022-08-01' self.header_parameters = {} self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' @@ -527,16 +491,81 @@ class AzureApiManagement(AzureRMModuleBaseExt): if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: - self.body[key] = kwargs[key] + if key == 'description': + self.body['properties']['description'] = kwargs[key] + elif key == 'authentication_settings': + self.body['properties']['authenticationSettings'] = {} + if kwargs[key].get('o_auth2') is not None: + self.body['properties']['authenticationSettings']['oAuth2'] = {} + for item in kwargs[key]['o_auth2'].keys(): + if item == 'authorization_server_id': + authorization_id = kwargs[key]['o_auth2']['authorization_server_id'] + self.body['properties']['authenticationSettings']['oAuth2']['authorizationServerId'] = authorization_id + elif item == 'scope': + self.body['properties']['authenticationSettings']['oAuth2']['scope'] = kwargs[key]['o_auth2']['scope'] + elif kwargs[key].get('openid') is not None: + self.body['properties']['authenticationSettings']['openid'] = {} + for item in kwargs[key]['openid'].keys(): + if item == 'openid_provider_id' and kwargs[key]['openid'].get('openid_provider_id') is not None: + openid_pro = kwargs[key]['openid'].get('openid_provider_id') + self.body['properties']['authenticationSettings']['openid']['openidProviderId'] = openid_pro + elif item == 'bearer_token_sending_methods' and kwargs[key]['openid'].get('bearer_token_sending_methods') is not None: + bearer_token = kwargs[key]['openid']['bearer_token_sending_methods'] + self.body['properties']['authenticationSettings']['openid']['bearerTokenSendingMethods'] = bearer_token + elif key == 'subscription_key_parameter_names': + self.body['properties']['subscriptionKeyParameterNames'] = kwargs[key] + elif key == 'type': + self.body['properties']['type'] = kwargs[key] + elif key == 'api_revision': + self.body['properties']['apiRevision'] = kwargs[key] + elif key == 'api_version': + self.body['properties']['apiVersion'] = kwargs[key] + elif key == 'is_current': + self.body['properties']['isCurrent'] = kwargs[key] + elif key == 'api_revision_description': + self.body['properties']['apiRevisionDescription'] = kwargs[key] + elif key == 'api_version_description': + self.body['properties']['apiVersionDescription'] = kwargs[key] + elif key == 'api_version_set_id': + self.body['properties']['apiVersionSetId'] = kwargs[key] + elif key == 'subscription_required': + self.body['properties']['subscriptionRequired'] = kwargs[key] + elif key == 'source_api_id': + self.body['properties']['sourceApiId'] = kwargs[key] + elif key == 'display_name': + self.body['properties']['displayName'] = kwargs[key] + elif key == 'service_url': + self.body['properties']['serviceUrl'] = kwargs[key] + elif key == 'protocols': + self.body['properties']['protocols'] = kwargs[key] + elif key == 'api_version_set': + self.body['properties']['apiVersionSet'] = {} + for item in kwargs[key].keys(): + if item == 'versioning_scheme': + self.body['properties']['apiVersionSet'] = kwargs[key].get('versioning_scheme') + elif item == 'version_query_name': + self.body['properties']['versionQueryName'] = kwargs[key].get('version_query_name') + elif item == 'version_header_name': + self.body['properties']['versionHeaderName'] = kwargs[key].get('version_header_name') + else: + self.body['properties'][item] = kwargs[key].get(item) + elif key == 'wsdl_selector': + self.body['properties']['wsdlSelector'] = {} + for item in kwargs[key].keys(): + if item == 'wsdl_service_name': + self.body['properties']['wsdlSelector']['wsdlServiceName'] = kwargs[key].get(item) + if item == 'wsdl_endpoint_name': + self.body['properties']['wsdlSelector']['wsdlEndpointName'] = kwargs[key].get(item) + elif key == 'api_type': + self.body['properties']['apiType'] = kwargs[key] + else: + self.body['properties'][key] = kwargs[key] - # https://docs.microsoft.com/en-us/azure/templates/microsoft.apimanagement/service/apis - self.inflate_parameters(self.module_arg_spec, self.body, 0) self.url = self.get_url() old_response = None response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_resource() @@ -552,11 +581,75 @@ class AzureApiManagement(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): + if self.body['properties'].get('description') is not None and \ + self.body['properties']['description'] != old_response['properties']['description']: + self.to_do = Actions.Update + elif self.body['properties'].get('authenticationSettings') is not None: + if old_response['properties'].get('authenticationSettings') is None: + self.to_do = Actions.Update + elif (self.body['properties']['authenticationSettings'].get('oAuth2') is not None and + self.body['properties']['authenticationSettings']['oAuth2'] != old_response['properties']['authenticationSettings'].get('oAuth2')): + self.to_do = Actions.Update + elif (self.body['properties']['authenticationSettings'].get('openid') is not None and + self.body['properties']['authenticationSettings']['openid'] != old_response['properties']['authenticationSettings'].get('openid')): + self.to_do = Actions.Update + elif self.body['properties'].get('subscriptionKeyParameterNames') is not None: + tt = old_response['properties'] + if old_response['properties'].get('subscriptionKeyParameterNames') is None: + self.to_do = Actions.Update + elif (not all(self.body['properties']['subscriptionKeyParameterNames'].get(item) == tt['subscriptionKeyParameterNames'].get(item) + for item in self.body['properties']['subscriptionKeyParameterNames'].keys())): + self.to_do = Actions.Update + elif (self.body['properties'].get('apiRevision') is not None and + self.body['properties']['apiRevision'] != old_response['properties'].get('apiRevision')): + self.to_do = Actions.Update + elif (self.body['properties'].get('apiVersion') is not None and + self.body['properties']['apiVersion'] != old_response['properties'].get('apiVersion')): + self.to_do == Actions.Update + elif (self.body['properties'].get('isCurrent') is not None and + self.body['properties']['isCurrent'] != old_response['properties'].get('isCurrent')): + self.to_do = Actions.Update + elif (self.body['properties'].get('apiRevisionDescription') is not None and self.body['properties']['apiRevisionDescription'] != + old_response['properties'].get('apiRevisionDescription')): + self.to_do = Actions.Update + elif (self.body['properties'].get('apiVersionDescription') is not None and + self.body['properties']['apiVersionDescription'] != old_response['properties'].get('apiVersionDescription')): + self.to_do = Actions.Update + elif (self.body['properties'].get('apiVersionSetId') is not None and + self.body['properties']['apiVersionSetId'] != old_response['properties'].get('apiVersionSetId')): + self.to_do = Actions.Update + elif (self.body['properties'].get('subscriptionRequired') is not None and + self.body['properties']['subscriptionRequired'] != old_response['properties'].get('subscriptionRequired')): + self.to_do = Actions.Update + elif (self.body['properties'].get('sourceApiId') is not None and + self.body['properties']['sourceApiId'] != old_response['properties'].get('sourceApiId')): + self.to_do = Actions.Update + elif (self.body['properties'].get('displayName') is not None and + self.body['properties']['displayName'] != old_response['properties'].get('displayName')): + self.to_do = Actions.Update + elif (self.body['properties'].get('serviceUrl') is not None and + self.body['properties']['serviceUrl'] != old_response['properties'].get('serviceUrl')): + self.to_do = Actions.Update + elif self.body['properties'].get('path') is not None and self.body['properties']['path'] != old_response['properties'].get('path'): + self.to_do = Actions.Update + elif (self.body['properties'].get('protocols') is not None and + self.body['properties']['protocols'] != old_response['properties'].get('protocols')): + self.to_do = Actions.Update + elif self.body['properties'].get('type') is not None and self.body['properties']['type'] != old_response['properties'].get('type'): + self.to_do = Actions.Update + elif self.body['properties'].get('apiType') is not None and self.body['properties']['apiType'] != old_response['properties'].get('apiType'): + self.to_do = Actions.Update + elif self.body['properties'].get('value') is not None and self.body['properties']['value'] != old_response['properties'].get('value'): + self.to_do = Actions.Update + elif self.body['properties'].get('format') is not None and self.body['properties']['format'] != old_response['properties'].get('format'): + self.to_do = Actions.Update + elif (self.body['properties'].get('wsdlSelector') is not None and + not all(self.body['properties']['wsdlSelector'][item] == old_response['properties']['wsdlSelector'].get(item) + for item in self.body['properties']['wsdlSelector'].keys())): + self.to_do = Actions.Update + elif (self.body['properties'].get('apiVersionSet') is not None and + not all(self.body['properties']['apiVersionSet'][item] == old_response['properties']['apiVersionSet'].get(item) + for item in self.body['properties']['apiVersionSet'].keys())): self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): @@ -605,10 +698,12 @@ class AzureApiManagement(AzureRMModuleBaseExt): except Exception as exc: self.log('Error while creating/updating the Api instance.') self.fail('Error creating the Api instance: {0}'.format(str(exc))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement_info.py index 30120b5e5..51e99b733 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagement_info.py @@ -139,7 +139,7 @@ class AzureApiManagementInfo(AzureRMModuleBaseExt): self.status_code = [200] self.query_parameters = {} - self.query_parameters['api-version'] = '2020-06-01-preview' + self.query_parameters['api-version'] = '2022-08-01' self.header_parameters = {} self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' @@ -155,7 +155,6 @@ class AzureApiManagementInfo(AzureRMModuleBaseExt): self.body[key] = kwargs[key] self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice.py index 8c694bec4..6d8a0aaf9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice.py @@ -113,32 +113,23 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): self.module_arg_spec = dict( resource_group=dict( type='str', - updatable=False, - disposition='resourceGroupName', required=True ), name=dict( type='str', - updatable=False, - disposition='serviceName', required=True ), location=dict( type='str', - updatable=False, - disposition='location' ), publisher_name=dict( type='str', - disposition='/properties/publisherName' ), publisher_email=dict( type='str', - disposition='/properties/publisherEmail' ), sku_name=dict( type='str', - disposition='/sku/name', choices=['Developer', 'Standard', 'Premium', @@ -147,7 +138,6 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): ), sku_capacity=dict( type='int', - disposition='/sku/capacity' ), state=dict( type='str', @@ -168,8 +158,10 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): self.to_do = Actions.NoAction self.body = {} + self.body['properties'] = {} + self.body['sku'] = {} self.query_parameters = {} - self.query_parameters['api-version'] = '2020-06-01-preview' + self.query_parameters['api-version'] = '2022-08-01' self.header_parameters = {} self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' @@ -182,15 +174,21 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: - self.body[key] = kwargs[key] - - self.inflate_parameters(self.module_arg_spec, self.body, 0) + if key == 'publisher_name': + self.body['properties']['publisherName'] = kwargs[key] + elif key == 'publisher_email': + self.body['properties']['publisherEmail'] = kwargs[key] + elif key == 'sku_name': + self.body['sku']['name'] = kwargs[key] + elif key == 'sku_capacity': + self.body['sku']['capacity'] = kwargs[key] + else: + self.body[key] = kwargs[key] old_response = None response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -225,12 +223,15 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): - self.to_do = Actions.Update + for key in self.body.keys(): + if key == 'properties': + for key in self.body['properties'].keys(): + if self.body['properties'][key] != old_response['properties'].get(key): + self.to_do = Actions.Update + elif key == 'sku': + for key in self.body['sku'].keys(): + if self.body['sku'][key] != old_response['sku'].get(key): + self.to_do = Actions.Update self.body['location'] = self.location if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): @@ -272,23 +273,34 @@ class AzureRMApiManagementService(AzureRMModuleBaseExt): def create_update_resource(self): # Creating / Updating the ApiManagementService instance. try: - response = self.mgmt_client.query(self.url, - 'PUT', - self.query_parameters, - self.header_parameters, - self.body, - self.status_code, - 600, - 30) + if self.to_do == Actions.Create: + response = self.mgmt_client.query(self.url, + 'PUT', + self.query_parameters, + self.header_parameters, + self.body, + self.status_code, + 600, + 30) + else: + response = self.mgmt_client.query(self.url, + 'PATCH', + self.query_parameters, + self.header_parameters, + self.body, + self.status_code, + 600, + 30) except Exception as exc: self.log('Error attempting to create the ApiManagementService instance.') self.fail('Error creating the ApiManagementService instance: {0}'.format(str(exc))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} - pass + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice_info.py index 663e87e78..5d686c98d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_apimanagementservice_info.py @@ -143,7 +143,7 @@ class AzureRMApiManagementServiceInfo(AzureRMModuleBaseExt): self.status_code = [200] self.query_parameters = {} - self.query_parameters['api-version'] = '2020-06-01-preview' + self.query_parameters['api-version'] = '2022-08-01' self.header_parameters = {} self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' @@ -156,7 +156,6 @@ class AzureRMApiManagementServiceInfo(AzureRMModuleBaseExt): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and self.name is not None): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway.py index f95766fa9..8d70dda89 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_appgateway.py @@ -519,6 +519,24 @@ options: - Whether host header should be picked from the host name of the backend HTTP settings. Default value is false. type: bool default: False + port: + description: + - Custom port which will be used for probing the backend servers. + - The valid value ranges from 1 to 65535. + - In case not set, port from http settings will be used. + - This property is valid for C(Standard_v2) and C(WAF_v2) only. + type: int + match: + description: + - Criterion for classifying a healthy probe response. + type: dict + suboptions: + status_codes: + description: + - Allowed ranges of healthy status codes. + - Default range of healthy status codes is 200-399. + type: list + elements: str backend_http_settings_collection: description: - Backend http settings of the application gateway resource. @@ -1419,6 +1437,54 @@ EXAMPLES = ''' max_request_body_size_in_kb: 128 file_upload_limit_in_mb: 100 +- name: Create application gateway with multi parameters + azure_rm_appgateway: + resource_group: myResourceGroup + name: myappgateway + sku: + name: standard_v2 + tier: standard_v2 + capacity: 2 + gateway_ip_configurations: + - subnet: + id: "{{ subnet_id }}" + name: app_gateway_ip_config + frontend_ip_configurations: + - name: sample_gateway_frontend_ip_config + public_ip_address: "pip{{ rpfx }}" + frontend_ports: + - port: 80 + name: http_frontend_port + backend_address_pools: + - name: test_backend_address_pool # empty pool which will receive attachment to NIC. + backend_http_settings_collection: + - port: 80 + protocol: http + cookie_based_affinity: enabled + name: sample_appgateway_http_settings + http_listeners: + - frontend_ip_configuration: sample_gateway_frontend_ip_config + frontend_port: http_frontend_port + protocol: http + name: http_listener + probes: + - name: testprobes01 + protocol: http + path: '/' + timeout: 30 + host: testazure + interval: 90 + port: 80 + match: + status_codes: + - 200 + request_routing_rules: + - rule_type: basic + backend_address_pool: test_backend_address_pool + backend_http_settings: sample_appgateway_http_settings + http_listener: http_listener + name: rule1 + - name: Stop an Application Gateway instance azure_rm_appgateway: resource_group: myResourceGroup @@ -1517,6 +1583,11 @@ ssl_policy_spec = dict( ) +match_spec = dict( + status_codes=dict(type='list', elements='str') +) + + probe_spec = dict( host=dict(type='str'), interval=dict(type='int'), @@ -1525,7 +1596,9 @@ probe_spec = dict( protocol=dict(type='str', choices=['http', 'https']), timeout=dict(type='int'), unhealthy_threshold=dict(type='int'), - pick_host_name_from_backend_http_settings=dict(type='bool', default=False) + pick_host_name_from_backend_http_settings=dict(type='bool', default=False), + port=dict(type='int'), + match=dict(type='dict', options=match_spec) ) @@ -2239,6 +2312,8 @@ class AzureRMApplicationGateways(AzureRMModuleBase): self.parameters["web_application_firewall_configuration"] = kwargs[key] elif key == "enable_http2": self.parameters["enable_http2"] = kwargs[key] + elif key == "tags": + self.parameters["tags"] = kwargs[key] response = None @@ -2272,7 +2347,7 @@ class AzureRMApplicationGateways(AzureRMModuleBase): (old_response['operational_state'] == 'Running' and self.gateway_state == 'started')): self.to_do = Actions.NoAction elif (self.parameters['location'] != old_response['location'] or - self.parameters['enable_http2'] != old_response['enable_http2'] or + self.parameters['enable_http2'] != old_response.get('enable_http2', False) or self.parameters['sku']['name'] != old_response['sku']['name'] or self.parameters['sku']['tier'] != old_response['sku']['tier'] or self.parameters['sku'].get('capacity', None) != old_response['sku'].get('capacity', None) or @@ -2296,6 +2371,11 @@ class AzureRMApplicationGateways(AzureRMModuleBase): else: self.to_do = Actions.NoAction + update_tags, new_tags = self.update_tags(old_response.get('tags')) + if update_tags: + self.to_do = Actions.Update + self.parameters["tags"] = new_tags + if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): self.log("Need to Create / Update the Application Gateway instance") diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall.py index f960f024d..692628317 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall.py @@ -354,40 +354,30 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): self.module_arg_spec = dict( resource_group=dict( type='str', - disposition='resource_group_name', required=True ), name=dict( type='str', - disposition='azure_firewall_name', required=True ), location=dict( type='str', - updatable=False, - disposition='/', - comparison='location' ), application_rule_collections=dict( type='list', elements='dict', - disposition='/properties/applicationRuleCollections', options=dict( priority=dict( type='int', - disposition='properties/*' ), action=dict( type='str', choices=['allow', 'deny'], - disposition='properties/action/type', - pattern='camelize' ), rules=dict( type='list', elements='raw', - disposition='properties/*', options=dict( name=dict( type='str' @@ -398,7 +388,6 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): source_addresses=dict( type='list', elements='str', - disposition='sourceAddresses' ), protocols=dict( type='list', @@ -406,7 +395,6 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): options=dict( type=dict( type='str', - disposition='protocolType' ), port=dict( type='str' @@ -416,12 +404,10 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): target_fqdns=dict( type='list', elements='raw', - disposition='targetFqdns' ), fqdn_tags=dict( type='list', elements='raw', - disposition='fqdnTags' ) ) ), @@ -433,23 +419,18 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): nat_rule_collections=dict( type='list', elements='dict', - disposition='/properties/natRuleCollections', options=dict( priority=dict( type='int', - disposition='properties/*' ), action=dict( type='str', - disposition='properties/action/type', choices=['snat', 'dnat'], - pattern='camelize' ), rules=dict( type='list', elements='dict', - disposition='properties/*', options=dict( name=dict( type='str' @@ -460,17 +441,14 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): source_addresses=dict( type='list', elements='str', - disposition='sourceAddresses' ), destination_addresses=dict( type='list', elements='str', - disposition='destinationAddresses' ), destination_ports=dict( type='list', elements='str', - disposition='destinationPorts' ), protocols=dict( type='list', @@ -478,11 +456,9 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ), translated_address=dict( type='str', - disposition='translatedAddress' ), translated_port=dict( type='str', - disposition='translatedPort' ) ) ), @@ -494,23 +470,18 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): network_rule_collections=dict( type='list', elements='dict', - disposition='/properties/networkRuleCollections', options=dict( priority=dict( type='int', - disposition='properties/*' ), action=dict( type='str', choices=['allow', 'deny'], - disposition='properties/action/type', - pattern='camelize' ), rules=dict( type='list', elements='dict', - disposition='properties/*', options=dict( name=dict( type='str' @@ -525,17 +496,14 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): source_addresses=dict( type='list', elements='str', - disposition='sourceAddresses' ), destination_addresses=dict( type='list', elements='str', - disposition='destinationAddresses' ), destination_ports=dict( type='list', elements='str', - disposition='destinationPorts' ) ) ), @@ -547,22 +515,12 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): ip_configurations=dict( type='list', elements='dict', - disposition='/properties/ipConfigurations', options=dict( subnet=dict( type='raw', - disposition='properties/subnet/id', - pattern=('/subscriptions/{subscription_id}/resourceGroups' - '/{resource_group}/providers/Microsoft.Network' - '/virtualNetworks/{virtual_network_name}/subnets' - '/{name}') ), public_ip_address=dict( type='raw', - disposition='properties/publicIPAddress/id', - pattern=('/subscriptions/{subscription_id}/resourceGroups' - '/{resource_group}/providers/Microsoft.Network' - '/publicIPAddresses/{name}') ), name=dict( type='str' @@ -579,6 +537,7 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): self.resource_group = None self.name = None self.body = {} + self.body['properties'] = {} self.results = dict(changed=False) self.mgmt_client = None @@ -587,7 +546,6 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): self.status_code = [200, 201, 202] self.to_do = Actions.NoAction - self.body = {} self.query_parameters = {} self.query_parameters['api-version'] = '2018-11-01' self.header_parameters = {} @@ -602,15 +560,171 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: - self.body[key] = kwargs[key] - - self.inflate_parameters(self.module_arg_spec, self.body, 0) + if key == 'application_rule_collections': + self.body['properties']['applicationRuleCollections'] = [] + for item in kwargs[key]: + app_rule = dict(properties={}) + if item.get('priority') is not None: + app_rule['properties']['priority'] = item['priority'] + if item.get('action') is not None: + app_rule['properties']['action'] = dict(type=item['action']) + if item.get('name') is not None: + app_rule['name'] = item['name'] + if item.get('rules') is not None: + app_rule['properties']['rules'] = [] + for value in item['rules']: + rule_value = {} + if value.get('name') is not None: + rule_value['name'] = value['name'] + if value.get('description') is not None: + rule_value['description'] = value['description'] + if value.get('source_addresses') is not None: + rule_value['sourceAddresses'] = value.get('source_addresses') + if value.get('target_fqdns') is not None: + rule_value['targetFqdns'] = value.get('target_fqdns') + if value.get('fqdn_tags') is not None: + rule_value['fqdnTags'] = value.get('fqdn_tags') + if value.get('protocols') is not None: + rule_value['protocols'] = [] + for pp in value['protocols']: + pro = {} + if pp.get('type') is not None: + pro['protocolType'] = pp.get('type') + if pp.get('port') is not None: + pro['port'] = pp.get('port') + rule_value['protocols'].append(pro) + app_rule['properties']['rules'].append(rule_value) + self.body['properties']['applicationRuleCollections'].append(app_rule) + elif key == 'nat_rule_collections': + self.body['properties']['natRuleCollections'] = [] + for item in kwargs[key]: + nat_rule = dict(properties={}) + if item.get('priority') is not None: + nat_rule['properties']['priority'] = item['priority'] + if item.get('action') is not None: + nat_rule['properties']['action'] = dict(type=item['action']) + if item.get('name') is not None: + nat_rule['name'] = item['name'] + if item.get('rules') is not None: + nat_rule['properties']['rules'] = [] + for value in item['rules']: + nat_value = {} + if value.get('name') is not None: + nat_value['name'] = value.get('name') + if value.get('description') is not None: + nat_value['description'] = value.get('description') + if value.get('source_addresses') is not None: + nat_value['sourceAddresses'] = value.get('source_addresses') + if value.get('destination_addresses') is not None: + nat_value['destinationAddresses'] = value.get('destination_addresses') + if value.get('destination_ports') is not None: + nat_value['destinationPorts'] = value.get('destination_ports') + if value.get('protocols') is not None: + nat_value['protocols'] = value.get('protocols') + if value.get('translated_address') is not None: + nat_value['translatedAddress'] = value.get('translated_address') + if value.get('translated_port') is not None: + nat_value['translatedPort'] = value.get('translated_port') + nat_rule['properties']['rules'].append(nat_value) + self.body['properties']['natRuleCollections'].append(nat_rule) + elif key == 'network_rule_collections': + self.body['properties']['networkRuleCollections'] = [] + for item in kwargs[key]: + network_rule = dict(properties={}) + if item.get('priority') is not None: + network_rule['properties']['priority'] = item['priority'] + if item.get('action') is not None: + network_rule['properties']['action'] = dict(type=item['action']) + if item.get('name') is not None: + network_rule['name'] = item['name'] + if item.get('rules') is not None: + network_rule['properties']['rules'] = [] + for value in item['rules']: + net_value = {} + if value.get('name') is not None: + net_value['name'] = value.get('name') + if value.get('description') is not None: + net_value['description'] = value.get('description') + if value.get('source_addresses') is not None: + net_value['sourceAddresses'] = value.get('source_addresses') + if value.get('destination_addresses') is not None: + net_value['destinationAddresses'] = value.get('destination_addresses') + if value.get('destination_ports') is not None: + net_value['destinationPorts'] = value.get('destination_ports') + if value.get('protocols') is not None: + net_value['protocols'] = value.get('protocols') + network_rule['properties']['rules'].append(net_value) + self.body['properties']['networkRuleCollections'].append(network_rule) + elif key == 'ip_configurations': + self.body['properties']['ipConfigurations'] = [] + for item in kwargs[key]: + ipconfig = dict(properties={}) + if item.get('subnet') is not None: + ipconfig['properties']['subnet'] = {} + if isinstance(item['subnet'], str): + ipconfig['properties']['subnet']['id'] = item['subnet'] + elif isinstance(item['subnet'], dict): + if item['subnet'].get('id') is not None: + ipconfig['properties']['subnet']['id'] = item['subnet'].get('id') + elif (item['subnet'].get('resource_group') is not None and item['subnet'].get('name') is not None and + item['subnet'].get('virtual_network_name') is not None): + ipconfig['properties']['subnet']['id'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + item['subnet'].get('resource_group') + + '/providers/Microsoft.Network/virtualNetworks/' + + item['subnet'].get('virtual_network_name') + + '/subnets/' + + item['subnet'].get('name')) + elif item['subnet'].get('name') is not None and item['subnet'].get('virtual_network_name') is not None: + ipconfig['properties']['subnet']['id'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + self.resource_group + + '/providers/Microsoft.Network/virtualNetworks/' + + item['subnet'].get('virtual_network_name') + + '/subnets/' + + item['subnet'].get('name')) + else: + self.fail("The ip_configuration's subnet config error") + else: + self.fail("The ip_configuration's subnet config error") + if item.get('public_ip_address') is not None: + ipconfig['properties']['publicIPAddress'] = {} + if isinstance(item.get('public_ip_address'), str): + ipconfig['properties']['publicIPAddress']['id'] = item.get('public_ip_address') + elif isinstance(item.get('public_ip_address'), dict): + if item['public_ip_address'].get('id') is not None: + ipconfig['properties']['publicIPAddress']['id'] = item['public_ip_address'].get('id') + elif item['public_ip_address'].get('resource_group') is not None and item['public_ip_address'].get('name') is not None: + ipconfig['properties']['publicIPAddress']['id'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + item['public_ip_address'].get('resource_group') + + '/providers/Microsoft.Network/publicIPAddresses/' + + item['public_ip_address'].get('name')) + elif item['public_ip_address'].get('name') is not None: + ipconfig['properties']['publicIPAddress']['id'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + self.resource_group + + '/providers/Microsoft.Network/publicIPAddresses/' + + item['public_ip_address'].get('name')) + else: + self.fail("The ip_configuration's public ip address config error") + else: + self.fail("The ip_configuration's public ip address config error") + + if item.get('name') is not None: + ipconfig['name'] = item['name'] + self.body['properties']['ipConfigurations'].append(ipconfig) + else: + self.body[key] = kwargs[key] old_response = None response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -642,11 +756,12 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): + update_tags, new_tags = self.update_tags(old_response.get('tags')) + if update_tags: + self.to_do = Actions.Update + self.body['tags'] = new_tags + + if not self.default_compare({}, self.body, old_response, '', dict(compare=[])): self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): @@ -705,10 +820,12 @@ class AzureRMAzureFirewalls(AzureRMModuleBaseExt): self.log('Error attempting to create the AzureFirewall instance.') self.fail('Error creating the AzureFirewall instance: {0}'.format(str(exc))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall_info.py index d86932693..a565ef886 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_azurefirewall_info.py @@ -140,7 +140,6 @@ class AzureRMAzureFirewallsInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and self.name is not None): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm.py index 77d6d92ed..863839329 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm.py @@ -255,7 +255,6 @@ class BackupAzureVM(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) changed = False @@ -296,10 +295,12 @@ class BackupAzureVM(AzureRMModuleBaseExt): self.fail( 'Error in creating/updating protection for Azure VM {0}'.format(str(e))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response @@ -322,10 +323,12 @@ class BackupAzureVM(AzureRMModuleBaseExt): self.log('Error attempting to stop protection.') self.fail('Error in disabling the protection: {0}'.format(str(e))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response @@ -348,10 +351,12 @@ class BackupAzureVM(AzureRMModuleBaseExt): self.log('Error attempting to delete backup.') self.fail('Error deleting the azure backup: {0}'.format(str(e))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response @@ -375,10 +380,12 @@ class BackupAzureVM(AzureRMModuleBaseExt): self.fail( 'Error while taking on-demand backup: {0}'.format(str(e))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm_info.py index b4ba22fc1..90ece65cb 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_backupazurevm_info.py @@ -130,7 +130,6 @@ class BackupAzureVMInfo(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) response = self.get_recovery_point_info() @@ -156,10 +155,12 @@ class BackupAzureVMInfo(AzureRMModuleBaseExt): self.log('Error in fetching recovery point.') self.fail('Error in fetching recovery point {0}'.format(str(e))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount.py index ac237294c..b5ff4d923 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount.py @@ -140,25 +140,19 @@ class AzureRMBatchAccount(AzureRMModuleBaseExt): type='str' ), location=dict( - type='str', - updatable=False, - disposition='/' + type='str' ), auto_storage_account=dict( type='raw' ), key_vault=dict( type='raw', - no_log=True, - updatable=False, - disposition='/' + no_log=True ), pool_allocation_mode=dict( default='batch_service', type='str', - choices=['batch_service', 'user_subscription'], - updatable=False, - disposition='/' + choices=['batch_service', 'user_subscription'] ), state=dict( type='str', @@ -212,8 +206,7 @@ class AzureRMBatchAccount(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(BatchManagementClient, - base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True) + base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_batchaccount() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount_info.py index fb61248e4..80930d6db 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_batchaccount_info.py @@ -112,9 +112,7 @@ class AzureRMBatchAccountInfo(AzureRMModuleBaseExt): response = [] self.mgmt_client = self.get_mgmt_svc_client(BatchManagementClient, - base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True) - + base_url=self._cloud_environment.endpoints.resource_manager) if self.resource_group is not None and self.name is not None: response = [self.get_batchaccount()] elif self.resource_group is not None: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint.py index 2f3a3d76f..ad4cb1303 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint.py @@ -659,7 +659,6 @@ class AzureRMCdnendpoint(AzureRMModuleBase): if not self.cdn_client: self.cdn_client = self.get_mgmt_svc_client(CdnManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2017-04-02') return self.cdn_client diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint_info.py index 9f89408d0..46a759847 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnendpoint_info.py @@ -232,7 +232,6 @@ class AzureRMCdnEndpointInfo(AzureRMModuleBase): self.cdn_client = self.get_mgmt_svc_client(CdnManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2017-04-02') if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile.py index 96761228f..ebac6f22f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile.py @@ -290,7 +290,6 @@ class AzureRMCdnprofile(AzureRMModuleBase): if not self.cdn_client: self.cdn_client = self.get_mgmt_svc_client(CdnManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2017-04-02') return self.cdn_client diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile_info.py index 92b9b7957..f4c599854 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cdnprofile_info.py @@ -253,7 +253,6 @@ class AzureRMCdnprofileInfo(AzureRMModuleBase): if not self.cdn_client: self.cdn_client = self.get_mgmt_svc_client(CdnManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2017-04-02') return self.cdn_client diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount.py index d1f3dd987..98d2c7149 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount.py @@ -426,7 +426,6 @@ class AzureRMCosmosDBAccount(AzureRMModuleBase): response = None self.mgmt_client = self.get_mgmt_svc_client(CosmosDBManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount_info.py index 61414272a..f80b2835e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_cosmosdbaccount_info.py @@ -431,7 +431,6 @@ class AzureRMCosmosDBAccountInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(CosmosDBManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name is not None: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore.py index eaecb9df5..b46907339 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore.py @@ -504,6 +504,7 @@ class AzureRMDatalakeStore(AzureRMModuleBase): supports_tags=True) def exec_module(self, **kwargs): + self.module.deprecate("The azure_rm_datalakestore.py will deprecated. Azure Data Lake Storage Gen1 retired on February 29,2024", version=(2.3, )) for key in list(self.module_arg_spec.keys()) + ['tags']: setattr(self, key, kwargs[key]) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore_info.py index 2417ff74a..8444a4c1c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_datalakestore_info.py @@ -312,6 +312,7 @@ class AzureRMDatalakeStoreInfo(AzureRMModuleBase): supports_tags=False) def exec_module(self, **kwargs): + self.module.deprecate("The azure_rm_datalakestore_info.py will deprecated. Azure Data Lake Storage Gen1 retired on February 29,2024", version=(2.3, )) for key in self.module_arg_spec: setattr(self, key, kwargs[key]) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment.py index 07cf93d8e..ef32b19dc 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_deployment.py @@ -84,7 +84,7 @@ options: description: - If I(state=present), template will be created. - If I(state=present) and deployment exists, it will be updated. - - If I(state=absent), the resource group will be removed. + - If I(state=absent), the deployment resource will be deleted. default: present type: str choices: @@ -498,7 +498,7 @@ class AzureRMDeploymentManager(AzureRMModuleBase): else: try: if self.get_resource_group(self.resource_group): - self.destroy_resource_group() + self.destroy_deployment_resource() self.results['changed'] = True self.results['msg'] = "deployment deleted" except Exception: @@ -572,12 +572,12 @@ class AzureRMDeploymentManager(AzureRMModuleBase): return deployment_result - def destroy_resource_group(self): + def destroy_deployment_resource(self): """ Destroy the targeted resource group """ try: - result = self.rm_client.resource_groups.begin_delete(self.resource_group) + result = self.rm_client.deployments.begin_delete(self.resource_group, self.name) result.wait() # Blocking wait till the delete is finished except Exception as e: if e.status_code == 404 or e.status_code == 204: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab.py index 1424be8c9..4d0ce4a36 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab.py @@ -157,7 +157,6 @@ class AzureRMDevTestLab(AzureRMModuleBase): self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2018-10-15') resource_group = self.get_resource_group(self.resource_group) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab_info.py index 6add55e59..91dcf737a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlab_info.py @@ -184,7 +184,6 @@ class AzureRMDevTestLabInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.resource_group is not None: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabarmtemplate_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabarmtemplate_info.py index 783a272dd..cf03aac99 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabarmtemplate_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabarmtemplate_info.py @@ -162,7 +162,6 @@ class AzureRMDtlArmTemplateInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifact_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifact_info.py index 9ec729257..35a084e5d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifact_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifact_info.py @@ -175,7 +175,6 @@ class AzureRMArtifactInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource.py index 87f19bbd9..7ae9290ea 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource.py @@ -220,7 +220,6 @@ class AzureRMDevTestLabArtifactsSource(AzureRMModuleBase): self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2018-10-15') old_response = self.get_devtestlabartifactssource() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource_info.py index 036a3da45..0b3dbeaba 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabartifactsource_info.py @@ -185,7 +185,6 @@ class AzureRMDtlArtifactSourceInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage.py index f24c6f7e5..6017ca2ed 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage.py @@ -205,7 +205,6 @@ class AzureRMDtlCustomImage(AzureRMModuleBase): response = None self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_customimage() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage_info.py index 2c6d559aa..e5c434f4a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabcustomimage_info.py @@ -162,7 +162,6 @@ class AzureRMDtlCustomImageInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment.py index 214ddbbe1..7fd3737fd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment.py @@ -190,7 +190,6 @@ class AzureRMDtlEnvironment(AzureRMModuleBase): response = None self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment_info.py index 4648ed1b7..31e2d1b42 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabenvironment_info.py @@ -175,7 +175,6 @@ class AzureRMDtlEnvironmentInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy.py index 2a3f2f953..7d19dd813 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy.py @@ -200,7 +200,6 @@ class AzureRMDtlPolicy(AzureRMModuleBase): response = None self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy_info.py index a8f3b104a..8801d09ad 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabpolicy_info.py @@ -173,7 +173,6 @@ class AzureRMDtlPolicyInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule.py index 060b3baa0..1907794c8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule.py @@ -172,7 +172,6 @@ class AzureRMSchedule(AzureRMModuleBase): response = None self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule_info.py index e366e0f99..c5ded5ffd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabschedule_info.py @@ -157,7 +157,6 @@ class AzureRMDtlScheduleInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name: self.results['schedules'] = self.get() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine.py index 62e7db77a..9a21fc532 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine.py @@ -393,7 +393,6 @@ class AzureRMVirtualMachine(AzureRMModuleBase): response = None self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_virtualmachine() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine_info.py index 24398136e..8a3692e2a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualmachine_info.py @@ -253,7 +253,6 @@ class AzureRMDtlVirtualMachineInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork.py index a47a8c8f9..15e3b67f6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork.py @@ -157,7 +157,6 @@ class AzureRMDevTestLabVirtualNetwork(AzureRMModuleBase): self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2018-10-15') resource_group = self.get_resource_group(self.resource_group) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py index 23392468b..0f6d59e02 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_devtestlabvirtualnetwork_info.py @@ -152,7 +152,6 @@ class AzureRMDevTestLabVirtualNetworkInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(DevTestLabsClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnsrecordset.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnsrecordset.py index 32448964a..1ac9983b4 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnsrecordset.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_dnsrecordset.py @@ -360,8 +360,10 @@ class AzureRMRecordSet(AzureRMModuleBase): resource_group=dict(type='str', required=True), relative_name=dict(type='str', required=True), zone_name=dict(type='str', required=True), - record_type=dict(choices=RECORD_ARGSPECS.keys(), required=True, type='str'), - record_mode=dict(choices=['append', 'purge'], default='purge'), + record_type=dict(choices=['A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SRV', 'TXT', 'SOA', 'CAA'], + required=True, + type='str'), + record_mode=dict(type='str', choices=['append', 'purge'], default='purge'), state=dict(choices=['present', 'absent'], default='present', type='str'), time_to_live=dict(type='int', default=3600), records=dict(type='list', elements='dict'), diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery.py index cb902ace7..9eb8ce397 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery.py @@ -85,24 +85,17 @@ class AzureRMGalleries(AzureRMModuleBaseExt): self.module_arg_spec = dict( resource_group=dict( type='str', - updatable=False, - disposition='resourceGroupName', required=True ), name=dict( type='str', - updatable=False, - disposition='galleryName', required=True ), location=dict( - type='str', - updatable=False, - disposition='/' + type='str' ), description=dict( type='str', - disposition='/properties/*' ), state=dict( type='str', @@ -123,6 +116,7 @@ class AzureRMGalleries(AzureRMModuleBaseExt): self.to_do = Actions.NoAction self.body = {} + self.body['properties'] = {} self.query_parameters = {} self.query_parameters['api-version'] = '2019-07-01' self.header_parameters = {} @@ -133,19 +127,19 @@ class AzureRMGalleries(AzureRMModuleBaseExt): supports_tags=True) def exec_module(self, **kwargs): - for key in list(self.module_arg_spec.keys()): + for key in list(self.module_arg_spec.keys()) + ['tags']: if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: - self.body[key] = kwargs[key] - - self.inflate_parameters(self.module_arg_spec, self.body, 0) + if key == 'description': + self.body['properties']['description'] = kwargs[key] + else: + self.body[key] = kwargs[key] old_response = None response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -180,28 +174,36 @@ class AzureRMGalleries(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): + if self.body.get('properties') is not None and self.body['properties']['description'] != old_response['properties']['description']: self.to_do = Actions.Update - self.body['properties'].pop('identifier', None) + else: + self.body['properties']['description'] = old_response['properties']['description'] - if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): - self.log('Need to Create / Update the Gallery instance') + update_tags, new_tags = self.update_tags(old_response.get('tags')) + if update_tags: + self.to_do = Actions.Update + self.body['tags'] = new_tags + if self.to_do == Actions.Create: + self.log('Need to Create the Gallery instance') if self.check_mode: self.results['changed'] = True return self.results - - response = self.create_update_resource() - + response = self.create_resource() # if not old_response: self.results['changed'] = True # else: # self.results['changed'] = old_response.__ne__(response) - self.log('Creation / Update done') + self.log('Creation done') + elif self.to_do == Actions.Update: + self.log('Need to Update the Gallery instance') + if self.check_mode: + self.results['changed'] = True + return self.results + response = self.update_resource() + # if not old_response: + self.results['changed'] = True + self.log('Update done') elif self.to_do == Actions.Delete: self.log('Gallery instance deleted') self.results['changed'] = True @@ -225,8 +227,33 @@ class AzureRMGalleries(AzureRMModuleBaseExt): return self.results - def create_update_resource(self): - # self.log('Creating / Updating the Gallery instance {0}'.format(self.)) + def update_resource(self): + # self.log('Updating the Gallery instance {0}'.format(self.)) + + try: + response = self.mgmt_client.query(self.url, + 'PATCH', + self.query_parameters, + self.header_parameters, + self.body, + self.status_code, + 600, + 30) + except Exception as exc: + self.log('Error attempting to update the Gallery instance.') + self.fail('Error updating the Gallery instance: {0}'.format(str(exc))) + + if hasattr(response, 'body'): + response = json.loads(response.body()) + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Updating fail, no match message return, return info as {0}".format(response)) + + return response + + def create_resource(self): + # self.log('Creating the Gallery instance {0}'.format(self.)) try: response = self.mgmt_client.query(self.url, @@ -241,10 +268,12 @@ class AzureRMGalleries(AzureRMModuleBaseExt): self.log('Error attempting to create the Gallery instance.') self.fail('Error creating the Gallery instance: {0}'.format(str(exc))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery_info.py index cd02bec28..d144c46fb 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_gallery_info.py @@ -128,7 +128,6 @@ class AzureRMGalleriesInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and self.name is not None): @@ -232,6 +231,8 @@ class AzureRMGalleriesInfo(AzureRMModuleBase): return [self.format_item(x) for x in results['value']] if results['value'] else [] def format_item(self, item): + if not item: + return d = { 'id': item['id'], 'name': item['name'], diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage.py index c14aedd4a..9a4542458 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage.py @@ -76,6 +76,14 @@ options: - V1 - V2 type: str + architecture: + description: + - This property allows you to specify the hardware architecture of the Virtual Machines. + - Arm64 is only supported with Hyper V Version 2. + choices: + - Arm64 + - x64 + type: str end_of_life_date: description: - The end of life date of the gallery Image Definition. @@ -162,6 +170,22 @@ options: description: - The product ID. type: str + features: + description: + - A list of gallery image features. + type: list + elements: dict + suboptions: + name: + description: + - The name of the gallery image feature. + type: str + required: True + value: + description: + - The value of the gallery image feature. + type: str + required: True state: description: - Assert the state of the GalleryImage. @@ -219,73 +243,60 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): self.module_arg_spec = dict( resource_group=dict( type='str', - updatable=False, - disposition='resourceGroupName', required=True ), gallery_name=dict( type='str', - updatable=False, - disposition='galleryName', required=True ), name=dict( type='str', - updatable=False, - disposition='galleryImageName', required=True ), location=dict( type='str', - updatable=False, - disposition='/' ), description=dict( type='str', - disposition='/properties/*' ), eula=dict( type='str', - disposition='/properties/*' ), privacy_statement_uri=dict( type='str', - disposition='/properties/privacyStatementUri' ), release_note_uri=dict( type='str', - disposition='/properties/releaseNoteUri' ), os_type=dict( type='str', - disposition='/properties/osType', choices=['windows', 'linux'] ), os_state=dict( type='str', - disposition='/properties/osState', choices=['generalized', 'specialized'] ), hypervgeneration=dict( type='str', - disposition='/properties/hyperVGeneration', choices=['V1', 'V2'] ), + architecture=dict( + type='str', + choices=['Arm64', + 'x64'] + ), end_of_life_date=dict( type='str', - disposition='/properties/endOfLifeDate' ), identifier=dict( type='dict', - disposition='/properties/*', options=dict( publisher=dict( type='str', required=True, - updatable=False ), offer=dict( type='str', @@ -299,11 +310,9 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): ), recommended=dict( type='dict', - disposition='/properties/*', options=dict( v_cpus=dict( type='dict', - disposition='vCPUs', options=dict( min=dict( type='int' @@ -328,18 +337,15 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): ), disallowed=dict( type='dict', - disposition='/properties/*', options=dict( disk_types=dict( type='list', elements='str', - disposition='diskTypes' ) ) ), purchase_plan=dict( type='dict', - disposition='/properties/purchasePlan', options=dict( name=dict( type='str' @@ -352,6 +358,20 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): ) ) ), + features=dict( + type='list', + elements='dict', + options=dict( + name=dict( + type='str', + required=True + ), + value=dict( + type='str', + required=True + ) + ) + ), state=dict( type='str', default='present', @@ -372,8 +392,9 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): self.to_do = Actions.NoAction self.body = {} + self.body['properties'] = {} self.query_parameters = {} - self.query_parameters['api-version'] = '2019-07-01' + self.query_parameters['api-version'] = '2022-03-03' self.header_parameters = {} self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' @@ -382,19 +403,51 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): supports_tags=True) def exec_module(self, **kwargs): - for key in list(self.module_arg_spec.keys()): + for key in list(self.module_arg_spec.keys()) + ['tags']: if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: - self.body[key] = kwargs[key] - - self.inflate_parameters(self.module_arg_spec, self.body, 0) + if key == 'description': + self.body['properties']['description'] = kwargs[key] + elif key == 'eula': + self.body['properties']['eula'] = kwargs[key] + elif key == 'privacy_statement_uri': + self.body['properties']['privacyStatementUri'] = kwargs[key] + elif key == 'release_note_uri': + self.body['properties']['releaseNoteUri'] = kwargs[key] + elif key == 'os_type': + self.body['properties']['osType'] = kwargs[key] + elif key == 'os_state': + self.body['properties']['osState'] = kwargs[key] + elif key == 'hypervgeneration': + self.body['properties']['hyperVGeneration'] = kwargs[key] + elif key == 'architecture': + self.body['properties']['architecture'] = kwargs[key] + elif key == 'end_of_life_date': + self.body['properties']['endOfLifeDate'] = kwargs[key] + elif key == 'identifier': + self.body['properties']['identifier'] = kwargs[key] + elif key == 'recommended': + self.body['properties']['recommended'] = {} + for item in kwargs[key].keys(): + if item == 'v_cpus': + self.body['properties']['recommended']['vCPUs'] = kwargs[key].get('v_cpus') + elif item == 'memory': + self.body['properties']['recommended']['memory'] = kwargs[key].get('memory') + elif key == 'disallowed': + self.body['properties']['disallowed'] = {} + self.body['properties']['disallowed']['diskTypes'] = kwargs[key].get('disk_types') + elif key == 'purchase_plan': + self.body['properties']['purchasePlan'] = kwargs[key] + elif key == 'features': + self.body['properties']['features'] = kwargs[key] + else: + self.body[key] = kwargs[key] old_response = None response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -432,11 +485,60 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): + if self.body['properties'].get('description') is not None and \ + self.body['properties']['description'] != old_response['properties'].get('description'): + self.to_do = Actions.Update + elif self.body['properties'].get('eula') is not None and self.body['properties']['eula'] != old_response['properties'].get('eula'): + self.to_do = Actions.Update + elif (self.body['properties'].get('privacyStatementUri') is not None and + self.body['properties']['privacyStatementUri'] != old_response['properties'].get('privacyStatementUri')): + self.to_do = Actions.Update + elif (self.body['properties'].get('releaseNoteUri') is not None and + self.body['properties']['releaseNoteUri'] != old_response['properties'].get('releaseNoteUri')): + self.to_do = Actions.Update + elif (self.body['properties'].get('osType') is not None and + self.body['properties']['osType'].lower() != old_response['properties'].get('osType', '').lower()): + self.to_do = Actions.Update + elif (self.body['properties'].get('osState') is not None and + self.body['properties']['osState'].lower() != old_response['properties'].get('osState', '').lower()): + self.to_do = Actions.Update + elif (self.body['properties'].get('hyperVGeneration') is not None and + self.body['properties']['hyperVGeneration'] != old_response['properties'].get('hyperVGeneration')): + self.to_do = Actions.Update + elif (self.body['properties'].get('architecture') is not None and + self.body['properties']['architecture'] != old_response['properties'].get('architecture')): + self.to_do = Actions.Update + elif (self.body['properties'].get('endOfLifeDate') is not None and + self.body['properties']['endOfLifeDate'] != old_response['properties'].get('endOfLifeDate')): + self.to_do = Actions.Update + elif (self.body['properties'].get('identifier') is not None and + self.body['properties']['identifier'].get('offer') != old_response['properties']['identifier'].get('offer') or + self.body['properties']['identifier'].get('sku') != old_response['properties']['identifier'].get('sku')): + self.to_do = Actions.Update + elif self.body['properties'].get('recommended') is not None: + if self.body['properties']['recommended'].get('vCPUS') is not None: + for item in self.body['properties']['recommended']['vCPUS'].keys(): + if self.body['properties']['recommended']['vCPUS'].get(item) != old_response['properties']['recommended']['vCPUS'].get(item): + self.to_do = Actions.Update + elif (self.body['properties']['recommended'].get('memory') is not None and + not all(self.body['properties']['recommended']['memory'].get(item) == old_response['properties']['recommended']['memory'].get(item) + for item in self.body['properties']['recommended']['memory'].keys())): + self.to_do = Actions.Update + elif (self.body['properties'].get('disallowed') is not None and + self.body['properties']['disallowed'].get('diskTypes') != old_response['properties']['disallowed'].get('diskTypes')): + self.to_do = Actions.Update + elif self.body['properties'].get('purchasePlan') is not None: + for item in self.body['properties']['purchasePlan'].keys(): + if self.body['properties']['purchasePlan'][item] != old_response['properties']['purchasePlan'].get(item): + self.to_do = Actions.Update + elif self.body['properties'].get('features') is not None: + if old_response['properties'].get('features') is None: + self.to_do = Actions.Update + else: + if not all(item in old_response['properties']['features'] for item in self.body['properties']['features']): + self.to_do = Actions.Update + update_tags, self.body['tags'] = self.update_tags(old_response.get('tags')) + if update_tags: self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): @@ -492,10 +594,12 @@ class AzureRMGalleryImages(AzureRMModuleBaseExt): self.log('Error attempting to create the GalleryImage instance.') self.fail('Error creating the GalleryImage instance: {0}'.format(str(exc))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage_info.py index 0f1c5020f..1b48f4f22 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimage_info.py @@ -159,7 +159,6 @@ class AzureRMGalleryImagesInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion.py index 9d61bf874..66a4dea6b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion.py @@ -125,6 +125,62 @@ options: description: - Storage account type. type: str + encryption: + description: + - Allows users to provide customer managed keys for encrypting the OS and data disks in the gallery artifact. + type: dict + suboptions: + data_disk_images: + description: + - A list of encryption specifications for data disk images. + type: list + elements: dict + suboptions: + disk_encryption_set_id: + description: + - A relative URI containing the resource ID of the disk encryption set. + type: str + lun: + description: + - This property specifies the logical unit number of the data disk. + - This value is used to identify data disks within the Virtual Machine and + therefore must be unique for each data disk attached to the Virtual Machine. + type: int + os_disk_image: + description: + - Contains encryption settings for an OS disk image. + type: dict + suboptions: + disk_encryption_set_id: + description: + - A relative URI containing the resource ID of the disk encryption set. + type: str + security_profile: + description: + - This property specifies the security profile of an OS disk image. + type: dict + suboptions: + confidential_vm_encryption_type: + description: + - Confidential VM encryption types. + type: dict + suboptions: + encrypted_vm_guest_state_only_with_pmk: + description: + - VM Guest State Only with PMK. + type: str + encrypted_with_cmk: + description: + - Encrypted with CMK. + type: str + encrypted_with_pmk: + description: + - Encrypted with PMK. + type: str + secure_vm_disk_encryption_set_id: + description: + - Secure VM disk encryption set id. + type: str managed_image: description: - Managed image reference, could be resource ID, or dictionary containing I(resource_group) and I(name) @@ -274,74 +330,40 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): self.module_arg_spec = dict( resource_group=dict( type='str', - updatable=False, - disposition='resourceGroupName', required=True ), gallery_name=dict( type='str', - updatable=False, - disposition='galleryName', required=True ), gallery_image_name=dict( type='str', - updatable=False, - disposition='galleryImageName', required=True ), name=dict( type='str', - updatable=False, - disposition='galleryImageVersionName', required=True ), tags=dict( type='dict', - updatable=False, - disposition='tags', - comparison='tags' ), location=dict( type='str', - updatable=False, - disposition='/', - comparison='location' ), storage_profile=dict( type='dict', - updatable=False, - disposition='/properties/storageProfile', - comparison='ignore', options=dict( source_image=dict( type='raw', - disposition='source/id', - purgeIfNone=True, - pattern=[('/subscriptions/{subscription_id}/resourceGroups' - '/{resource_group}/providers/Microsoft.Compute' - '/images/{name}'), - ('/subscriptions/{subscription_id}/resourceGroups' - '/{resource_group}/providers/Microsoft.Compute' - '/galleries/{gallery_name}/images/{gallery_image_name}' - '/versions/{version}')] ), os_disk=dict( type='dict', - disposition='osDiskImage', - purgeIfNone=True, - comparison='ignore', options=dict( source=dict( type='raw', - disposition='source/id', - pattern=('/subscriptions/{subscription_id}/resourceGroups' - '/{resource_group}/providers/Microsoft.Compute' - '/snapshots/{name}') ), host_caching=dict( type='str', - disposition='hostCaching', default="None", choices=["ReadOnly", "ReadWrite", "None"] ) @@ -350,22 +372,15 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): data_disks=dict( type='list', elements='raw', - disposition='dataDiskImages', - purgeIfNone=True, options=dict( lun=dict( type='int' ), source=dict( type='raw', - disposition="source/id", - pattern=('/subscriptions/{subscription_id}/resourceGroups' - '/{resource_group}/providers/Microsoft.Compute' - '/snapshots/{name}') ), host_caching=dict( type='str', - disposition='hostCaching', default="None", choices=["ReadOnly", "ReadWrite", "None"] ) @@ -375,57 +390,87 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): ), publishing_profile=dict( type='dict', - disposition='/properties/publishingProfile', options=dict( target_regions=dict( type='list', elements='raw', - disposition='targetRegions', options=dict( name=dict( type='str', required=True, - comparison='location' ), regional_replica_count=dict( type='int', - disposition='regionalReplicaCount' ), storage_account_type=dict( type='str', - disposition='storageAccountType' + ), + encryption=dict( + type='dict', + options=dict( + data_disk_images=dict( + type='list', + elements='dict', + options=dict( + disk_encryption_set_id=dict( + type='str', + ), + lun=dict( + type='int' + ) + ) + ), + os_disk_image=dict( + type='dict', + options=dict( + disk_encryption_set_id=dict( + type='str', + ), + security_profile=dict( + type='dict', + options=dict( + confidential_vm_encryption_type=dict( + type='dict', + options=dict( + encrypted_vm_guest_state_only_with_pmk=dict( + type='str', + ), + encrypted_with_cmk=dict( + type='str', + ), + encrypted_with_pmk=dict( + type='str', + ) + ) + ), + secure_vm_disk_encryption_set_id=dict( + type='str', + ) + ) + ) + ) + ) + ) ) ) ), managed_image=dict( type='raw', - pattern=('/subscriptions/{subscription_id}/resourceGroups' - '/{resource_group}/providers/Microsoft.Compute' - '/images/{name}'), - comparison='ignore' ), snapshot=dict( type='raw', - pattern=('/subscriptions/{subscription_id}/resourceGroups' - '/{resource_group}/providers/Microsoft.Compute' - '/snapshots/{name}'), - comparison='ignore' ), replica_count=dict( type='int', - disposition='replicaCount' ), exclude_from_latest=dict( type='bool', - disposition='excludeFromLatest' ), end_of_life_date=dict( type='str', - disposition='endOfLifeDate' ), storage_account_type=dict( type='str', - disposition='storageAccountType', choices=['Standard_LRS', 'Standard_ZRS'] ) @@ -453,8 +498,9 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): self.to_do = Actions.NoAction self.body = {} + self.body['properties'] = {} self.query_parameters = {} - self.query_parameters['api-version'] = '2019-07-01' + self.query_parameters['api-version'] = '2022-03-03' self.header_parameters = {} self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' @@ -469,9 +515,182 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): if key == 'tags': self.body[key] = kwargs[key] elif kwargs[key] is not None: - self.body[key] = kwargs[key] - - self.inflate_parameters(self.module_arg_spec, self.body, 0) + if key == 'location': + self.body['location'] = kwargs[key] + elif key == 'storage_profile': + self.body['properties']['storageProfile'] = {} + if kwargs[key].get('source_image') is not None: + self.body['properties']['storageProfile']['source'] = {} + if isinstance(kwargs[key].get('source_image'), str): + self.body['properties']['storageProfile']['source']['id'] = kwargs[key].get('source_image') + elif isinstance(kwargs[key].get('source_image'), dict): + if kwargs[key]['source_image'].get('id') is not None: + self.body['properties']['storageProfile']['source']['id'] = kwargs[key]['source_image'].get('id') + if kwargs[key]['source_image'].get('resource_group') is not None and kwargs[key]['source_image'].get('name') is not None: + self.body['properties']['storageProfile']['source']['id'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + kwargs[key]['source_image'].get('resource_group') + + '/providers/Microsoft.Compute/images/' + + kwargs[key]['source_image'].get('name')) + elif (kwargs[key]['source_image'].get('resource_group') is not None and + kwargs[key]['source_image'].get('gallery_name') is not None and + kwargs[key]['source_image'].get('gallery_image_name') is not None and kwargs[key]['source_image'].get('version') is not None): + self.body['properties']['storageProfile']['source']['id'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + kwargs[key]['source_image'].get('resource_group') + + '/providers/Microsoft.Compute/galleries/' + + kwargs[key]['source_image'].get('gallery_name') + + '/images/' + + kwargs[key]['source_image'].get('gallery_image_name') + + '/versions/' + + kwargs[key]['source_image'].get('version')) + else: + self.fail("The source_image parameters config errors") + else: + self.fail("The source_image parameters config errors") + if kwargs[key].get('os_disk') is not None: + self.body['properties']['storageProfile']['osDiskImage'] = {} + if kwargs[key]['os_disk'].get('host_caching') is not None: + self.body['properties']['storageProfile']['osDiskImage']['hostCaching'] = kwargs[key]['os_disk'].get('host_caching') + if kwargs[key]['os_disk'].get('source') is not None: + self.body['properties']['storageProfile']['osDiskImage']['source'] = {} + if isinstance(kwargs[key]['os_disk']['source'], str): + self.body['properties']['storageProfile']['osDiskImage']['source']['id'] = kwargs[key]['os_disk']['source'] + elif isinstance(kwargs[key]['os_disk']['source'], dict): + if kwargs[key]['os_disk']['source'].get('id') is not None: + self.body['properties']['storageProfile']['osDiskImage']['source']['id'] = kwargs[key]['os_disk']['source'].get('id') + if kwargs[key]['os_disk']['source'].get('resource_group') is not None and \ + kwargs[key]['os_disk']['source'].get('name') is not None: + resource_group = kwargs[key]['os_disk']['source'].get('resource_group') + self.body['properties']['storageProfile']['osDiskImage']['source']['id'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + resource_group + + '/providers/Microsoft.Compute/snapshots/' + + kwargs[key]['os_disk']['source'].get('name')) + else: + self.fail("The os_disk.source parameters config errors") + + else: + self.fail("The os_disk.source parameters config errors") + + if kwargs[key].get('data_disks') is not None: + self.body['properties']['storageProfile']['dataDiskImages'] = [] + data_disk = {} + for item in kwargs[key].get('data_disks'): + if item.get('lun') is not None: + data_disk['lun'] = item['lun'] + if item.get('source') is not None: + data_disk['source'] = {} + if isinstance(item.get('source'), str): + data_disk['source']['id'] = item.get('source') + elif isinstance(item.get('source'), dict): + if item['source'].get('id') is not None: + data_disk['source']['id'] = item['source'].get('id') + elif item['source'].get('resource_group') is not None and item['source'].get('name') is not None: + data_disk['source']['id'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + item['source'].get('resource_group') + + '/providers/Microsoft.Compute/snapshots/' + + item['source'].get('name')) + else: + self.fail("The data_disk.source parameters config errors") + else: + self.fail("The data_disk.source parameters config errors") + if item.get('host_caching') is not None: + data_disk['hostCaching'] = item['host_caching'] + elif key == 'publishing_profile': + self.body['properties']['publishingProfile'] = {} + if kwargs['publishing_profile'].get('target_regions') is not None: + self.body['properties']['publishingProfile']['targetRegions'] = [] + for item in kwargs['publishing_profile']['target_regions']: + target_regions = {} + for value in item.keys(): + if value == 'name': + target_regions[value] = item[value] + elif value == 'regional_replica_count': + target_regions['regionalReplicaCount'] = item[value] + elif value == 'storage_account_type': + target_regions['storageAccountType'] = item[value] + elif value == 'encryption': + target_regions['encryption'] = {} + if item[value].get('data_disk_images') is not None: + target_regions['encryption']['dataDiskImages'] = [] + for tt in item[value]['data_disk_images']: + disk_image = {} + if tt.get('lun') is not None: + disk_image['lun'] = tt['lun'] + if tt.get('disk_encryption_set_id') is not None: + disk_image['diskEncryptionSetId'] = tt['disk_encryption_set_id'] + target_regions['encryption']['dataDiskImages'].append(disk_image) + + if item['encryption'].get('os_disk_image') is not None: + target_regions['encryption']['osDiskImage'] = {} + if item['encryption']['os_disk_image'].get('disk_encryption_set_id') is not None: + disk_encryption_set_id = item['encryption']['os_disk_image']['disk_encryption_set_id'] + target_regions['encryption']['osDiskImage']['diskEncryptionSetId'] = disk_encryption_set_id + if item['encryption']['os_disk_image'].get('security_profile') is not None: + target_regions['encryption']['osDiskImage']['securityProfile'] = {} + if item['encryption']['os_disk_image']['security_profile'].get('secure_vm_disk_encryption_set_id') is not None: + secure_id = item['encryption']['os_disk_image']['security_profile']['secure_vm_disk_encryption_set_id'] + target_regions['encryption']['osDiskImage']['securityProfile']['secureVMDiskEncryptionSetId'] = secure_id + + if item['encryption']['os_disk_image']['security_profile'].get('confidential_vm_encryption_type') is not None: + target_regions['encryption']['osDiskImage']['securityProfile']['confidentialVMEncryptionType'] = {} + security = item['encryption']['os_disk_image']['security_profile']['confidential_vm_encryption_type'] + tt = target_regions['encryption']['osDiskImage']['securityProfile']['confidentialVMEncryptionType'] + if security.get('encrypted_vm_guest_state_only_with_pmk') is not None: + tt['EncryptedVMGuestStateOnlyWithPmk'] = security.get('encrypted_vm_guest_state_only_with_pmk') + if security.get('encrypted_with_cmk') is not None: + tt['EncryptedWithCmk'] = security.get('encrypted_with_cmk') + if security.get('encrypted_with_pmk') is not None: + tt['EncryptedWithPmk'] = security.get('encrypted_with_pmk') + self.body['properties']['publishingProfile']['targetRegions'].append(target_regions) + if kwargs[key].get('managed_image') is not None: + if isinstance(kwargs[key]['managed_image'], str): + self.body['properties']['publishingProfile']['managed_image'] = kwargs[key]['managed_image'] + elif isinstance(kwargs[key]['managed_image'], dict): + if kwargs[key]['managed_image'].get('id') is not None: + self.body['properties']['publishingProfile']['managed_image'] = kwargs[key]['managed_image']['id'] + elif kwargs[key]['managed_image'].get('resource_group') is not None and kwargs[key]['managed_image'].get('name') is not None: + self.body['properties']['publishingProfile']['managed_image'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + kwargs[key]['managed_image'].get('resource_group') + + '/providers/Microsoft.Compute/images/' + + kwargs[key]['managed_image'].get('name')) + else: + self.fail("The managed_image parameters config errors") + else: + self.fail("The managed_image parameters config errors") + if kwargs[key].get('snapshot') is not None: + if isinstance(kwargs[key].get('snapshot'), str): + self.body['properties']['publishingProfile']['snapshot'] = kwargs[key].get('snapshot') + elif isinstance(kwargs[key].get('snapshot'), dict): + if kwargs[key]['snapshot'].get('id') is not None: + self.body['properties']['publishingProfile']['snapshot'] = kwargs[key]['snapshot'].get('id') + elif kwargs[key]['snapshot'].get('resource_group') is not None and kwargs[key]['snapshot'].get('name') is not None: + self.body['properties']['publishingProfile']['snapshot'] = ('/subscriptions/' + + self.subscription_id + + '/resourceGroups/' + + kwargs[key]['snapshot'].get('resource_group') + + '/providers/Microsoft.Compute/snapshots/' + + kwargs[key]['snapshot'].get('name')) + else: + self.fail("The managed_image parameters config errors") + else: + self.fail("The managed_image parameters config errors") + if kwargs[key].get('replica_count') is not None: + self.body['properties']['publishingProfile']['replicaCount'] = kwargs[key].get('replica_count') + if kwargs[key].get('exclude_from_latest') is not None: + self.body['properties']['publishingProfile']['excludeFromLatest'] = kwargs[key].get('exclude_from_latest') + if kwargs[key].get('end_of_life_date') is not None: + self.body['properties']['publishingProfile']['endOfLifeDate'] = kwargs[key].get('end_of_life_date') + if kwargs[key].get('storage_account_type') is not None: + self.body['properties']['publishingProfile']['storageAccountType'] = kwargs[key].get('storage_account_type') # keep backward compatibility snapshot = self.body.get('properties', {}).get('publishingProfile', {}).pop('snapshot', None) @@ -485,7 +704,6 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -531,12 +749,19 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): self.tags = newtags self.body['tags'] = self.tags self.to_do = Actions.Update - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): - self.to_do = Actions.Update + if self.body['properties'].get('publishingProfile') is not None: + for key in self.body['properties']['publishingProfile'].keys(): + if key == 'targetRegions': + result = dict(compare=[]) + modifies = {'/*/name': {'updatable': True, 'comparison': 'location'}} + if not self.default_compare(modifies, self.body['properties']['publishingProfile'][key], + old_response['properties']['publishingProfile'][key], '', result): + self.to_do = Actions.Update + elif key == 'endOfLifeDate': + if self.body['properties']['publishingProfile'][key].lower() != old_response['properties']['publishingProfile'][key].lower(): + self.to_do = Actions.Update + elif self.body['properties']['publishingProfile'].get(key) != old_response['properties']['publishingProfile'].get(key): + self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): self.log('Need to Create / Update the GalleryImageVersion instance') @@ -583,10 +808,12 @@ class AzureRMGalleryImageVersions(AzureRMModuleBaseExt): self.log('Error attempting to create the GalleryImageVersion instance.') self.fail('Error creating the GalleryImageVersion instance: {0}'.format(str(exc))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) while response['properties']['provisioningState'] == 'Creating': time.sleep(60) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion_info.py index b4c7e89a2..2eebb73e7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_galleryimageversion_info.py @@ -150,7 +150,6 @@ class AzureRMGalleryImageVersionsInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and @@ -258,6 +257,8 @@ class AzureRMGalleryImageVersionsInfo(AzureRMModuleBase): return [self.format_item(x) for x in results['response']] if results['response'] else [] def format_item(self, item): + if not item: + return None d = { 'id': item['id'], 'name': item['name'], diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster.py index 2ce7e16f3..b2121cd27 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster.py @@ -322,7 +322,6 @@ class AzureRMClusters(AzureRMModuleBase): response = None self.mgmt_client = self.get_mgmt_svc_client(HDInsightManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster_info.py index afb3211ea..b50d51215 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_hdinsightcluster_info.py @@ -229,7 +229,6 @@ class AzureRMHDInsightclusterInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(HDInsightManagementClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.name is not None: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice.py index be007b8d8..d26062244 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevice.py @@ -378,8 +378,8 @@ class AzureRMIoTDevice(AzureRMModuleBase): elif self.auth_method == 'self_signed': response = self.mgmt_client.update_device_with_certificate_authority(self.name, self.status, iot_edge=self.edge_enabled) elif self.auth_method == 'certificate_authority': - response = self.mgmt_client.update_device_with_x509(self.name, device['etag'], self.primary_thumbprint, - self.secondary_thumbprint, self.status, iot_edge=self.edge_enabled) + response = self.mgmt_client.update_device_with_x509(self.name, device['etag'], self.primary_key, + self.secondary_key, self.status, iot_edge=self.edge_enabled) return self.format_item(response) except Exception as exc: @@ -394,7 +394,7 @@ class AzureRMIoTDevice(AzureRMModuleBase): response = self.mgmt_client.create_device_with_certificate_authority(self.name, self.status, iot_edge=self.edge_enabled) elif self.auth_method == 'certificate_authority': response = self.mgmt_client.create_device_with_x509(self.name, - self.primary_thumbprint, self.secondary_thumbprint, self.status, iot_edge=self.edge_enabled) + self.primary_key, self.secondary_key, self.status, iot_edge=self.edge_enabled) return self.format_item(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevicemodule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevicemodule.py index 2f2ad679d..274440754 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevicemodule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_iotdevicemodule.py @@ -291,11 +291,11 @@ class AzureRMIoTDeviceModule(AzureRMModuleBase): try: if self.auth_method == 'sas': response = self.mgmt_client.update_module_with_sas(self.device, self.name, self.managed_by, self.etag, self.primary_key, self.secondary_key) - elif self.auth_method == 'self_signed': - response = self.mgmt_client.update_module_with_certificate_authority(self.device, self.name, self.managed_by, self.etag) elif self.auth_method == 'certificate_authority': + response = self.mgmt_client.update_module_with_certificate_authority(self.device, self.name, self.managed_by, self.etag) + elif self.auth_method == 'self_signed': response = self.mgmt_client.update_module_with_x509(self.device, - self.name, self.managed_by, self.etag, self.primary_thumbprint, self.secondary_thumbprint) + self.name, self.managed_by, self.etag, self.primary_key, self.secondary_key) return self.format_module(response) except Exception as exc: @@ -309,11 +309,11 @@ class AzureRMIoTDeviceModule(AzureRMModuleBase): try: if self.auth_method == 'sas': response = self.mgmt_client.create_module_with_sas(self.device, self.name, self.managed_by, self.primary_key, self.secondary_key) - elif self.auth_method == 'self_signed': - response = self.mgmt_client.create_module_with_certificate_authority(self.device, self.name, self.managed_by) elif self.auth_method == 'certificate_authority': + response = self.mgmt_client.create_module_with_certificate_authority(self.device, self.name, self.managed_by) + elif self.auth_method == 'self_signed': response = self.mgmt_client.create_module_with_x509(self.device_id, - self.name, self.managed_by, self.primary_thumbprint, self.secondary_thumbprint) + self.name, self.managed_by, self.primary_key, self.secondary_key) return self.format_module(response) except Exception as exc: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault.py index efeddaacc..96d2d589e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault.py @@ -382,7 +382,6 @@ class AzureRMVaults(AzureRMModuleBase): self.mgmt_client = self.get_mgmt_svc_client(KeyVaultManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version="2021-10-01") resource_group = self.get_resource_group(self.resource_group) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault_info.py index d7b54515f..af1a245e9 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvault_info.py @@ -261,7 +261,6 @@ class AzureRMKeyVaultInfo(AzureRMModuleBase): self._client = self.get_mgmt_svc_client(KeyVaultManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version="2021-10-01") if self.name: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey.py index 54cc6eff6..d094a4ac4 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey.py @@ -117,6 +117,7 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.keyvault.keys import KeyClient + from azure.core.exceptions import ResourceNotFoundError from datetime import datetime except ImportError: # This is handled in azure_rm_common @@ -191,10 +192,12 @@ class AzureRMKeyVaultKey(AzureRMModuleBase): if self.state == 'absent': changed = True - except Exception: + except ResourceNotFoundError as ec: # Key doesn't exist if self.state == 'present': changed = True + except Exception as ec: + self.fail("Find the key vault secret got exception, exception as {0}".format(ec)) self.results['changed'] = changed self.results['state'] = results diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey_info.py index b59f89b33..979d09f49 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultkey_info.py @@ -195,6 +195,7 @@ keyvaults: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase try: + from azure.core.exceptions import ResourceNotFoundError from azure.keyvault.keys import KeyClient except ImportError: # This is handled in azure_rm_common @@ -282,7 +283,7 @@ def keyitem_to_dict(keyitem): kid=keyitem._id, version=keyitem.version, tags=keyitem._tags, - manged=keyitem._managed, + managed=keyitem._managed, attributes=dict( enabled=keyitem.enabled, not_before=keyitem.not_before, @@ -398,9 +399,10 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): self.log("Response : {0}".format(response)) results.append(response) - except Exception as e: - self.fail(e) + except ResourceNotFoundError as e: self.log("Did not find the key vault key {0}: {1}".format(self.name, str(e))) + except Exception as ec: + self.fail("Find the key vault key got a exception as {0}".format(ec)) return results def get_key_versions(self): @@ -422,7 +424,7 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): if self.has_tags(item['tags'], self.tags): results.append(item) except Exception as e: - self.log("Did not find key versions {0} : {1}.".format(self.name, str(e))) + self.fail("Did not find key versions {0} : {1}.".format(self.name, str(e))) return results def list_keys(self): @@ -444,7 +446,7 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): if self.has_tags(item['tags'], self.tags): results.append(item) except Exception as e: - self.log("Did not find key vault in current subscription {0}.".format(str(e))) + self.fail("Did not find key vault in current subscription {0}.".format(str(e))) return results def get_deleted_key(self): @@ -465,8 +467,11 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): self.log("Response : {0}".format(response)) results.append(response) - except Exception as e: - self.log("Did not find the key vault key {0}: {1}".format(self.name, str(e))) + except ResourceNotFoundError as ec: + self.log("Did not find the key vault key {0}: {1}".format(self.name, str(ec))) + except Exception as ec: + self.fail("Find the key vault key got a exception {0}".format(str(ec))) + return results def list_deleted_keys(self): @@ -488,7 +493,7 @@ class AzureRMKeyVaultKeyInfo(AzureRMModuleBase): if self.has_tags(item['tags'], self.tags): results.append(item) except Exception as e: - self.log("Did not find key vault in current subscription {0}.".format(str(e))) + self.fail("Did not find key vault in current subscription {0}.".format(str(e))) return results diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret.py index 98a5e0e78..f36c86f1a 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret.py @@ -43,6 +43,14 @@ options: description: - Optional valid-from datetime for secret type: str + recover_if_need: + description: + - Whether to permanently recover delete secrets. + type: bool + purge_if_need: + description: + - Whether to permanently delete secrets. + type: bool state: description: - Assert the state of the subnet. Use C(present) to create or update a secret and C(absent) to delete a secret . @@ -76,6 +84,18 @@ EXAMPLES = ''' secret_name: MySecret keyvault_uri: https://contoso.vault.azure.net/ state: absent + +- name: Recover a delete secret + azure_rm_keyvaultsecret: + secret_name: MySecret + keyvault_uri: https://contoso.vault.azure.net/ + recover_if_need: true + +- name: Purge a delete secret + azure_rm_keyvaultsecret: + secret_name: MySecret + keyvault_uri: https://contoso.vault.azure.net/ + purge_if_need: true ''' RETURN = ''' @@ -96,6 +116,8 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.keyvault.secrets import SecretClient + from azure.core.exceptions import ResourceNotFoundError + from azure.core.exceptions import HttpResponseError import dateutil.parser except ImportError: # This is handled in azure_rm_common @@ -114,6 +136,8 @@ class AzureRMKeyVaultSecret(AzureRMModuleBase): secret_expiry=dict(type='str', no_log=True), keyvault_uri=dict(type='str', no_log=True, required=True), state=dict(type='str', default='present', choices=['present', 'absent']), + recover_if_need=dict(type='bool'), + purge_if_need=dict(type='bool'), content_type=dict(type='str') ) @@ -135,6 +159,8 @@ class AzureRMKeyVaultSecret(AzureRMModuleBase): self.data_creds = None self.client = None self.tags = None + self.recover_if_need = None + self.purge_if_need = None self.content_type = None super(AzureRMKeyVaultSecret, self).__init__(self.module_arg_spec, @@ -162,10 +188,12 @@ class AzureRMKeyVaultSecret(AzureRMModuleBase): elif self.secret_value and results['secret_value'] != self.secret_value: changed = True - except Exception as ec: + except ResourceNotFoundError as ec: # Secret doesn't exist if self.state == 'present': changed = True + except Exception as ec2: + self.fail("Find the key vault secret got exception, exception as {0}".format(str(ec2))) self.results['changed'] = changed self.results['state'] = results @@ -181,9 +209,21 @@ class AzureRMKeyVaultSecret(AzureRMModuleBase): if not self.check_mode: # Create secret if self.state == 'present' and changed: - results['secret_id'] = self.create_update_secret(self.secret_name, self.secret_value, self.tags, self.content_type, valid_from, expiry) + if self.get_delete_secret(self.secret_name): + if self.recover_if_need: + results['secret_id'] = self.recover_delete_secret(self.secret_name) + status = 'Recover' + elif self.purge_if_need: + self.purge_deleted_secret(self.secret_name) + status = 'Purged' + else: + self.fail("Secret {0} is currently in a deleted but recoverable state, and its name cannot be reused; in this state,\ + the secret can only be recovered or purged.".format(self.secret_name)) + else: + results['secret_id'] = self.create_update_secret(self.secret_name, self.secret_value, self.tags, self.content_type, valid_from, expiry) + status = 'Created' self.results['state'] = results - self.results['state']['status'] = 'Created' + self.results['state']['status'] = status # Delete secret elif self.state == 'absent' and changed: results['secret_id'] = self.delete_secret(self.secret_name) @@ -225,6 +265,31 @@ class AzureRMKeyVaultSecret(AzureRMModuleBase): result = self.get_poller_result(deleted_secret) return result.properties._id + def recover_delete_secret(self, name): + ''' Recover a delete secret ''' + try: + recover_delete_secret = self.client.begin_recover_deleted_secret(name) + result = self.get_poller_result(recover_delete_secret) + return result._id + except HttpResponseError as ec: + self.fail("Recover the delete secret fail, detail info {0}".format(ec)) + + def purge_deleted_secret(self, name): + ''' Purge delete secret ''' + try: + purge_deleted_secret = self.client.purge_deleted_secret(name) + return purge_deleted_secret + except HttpResponseError as ec: + self.fail("Purge delete secret fail, detail info {0}".format(ec)) + + def get_delete_secret(self, name): + ''' Get delete secret ''' + try: + self.client.get_deleted_secret(name=name) + except ResourceNotFoundError: + return False + return True + def main(): AzureRMKeyVaultSecret() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret_info.py index b612dce36..f03977285 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_keyvaultsecret_info.py @@ -163,12 +163,14 @@ from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common try: from azure.keyvault.secrets import SecretClient + from azure.core.exceptions import ResourceNotFoundError except ImportError: # This is handled in azure_rm_common pass def secretbundle_to_dict(bundle): + return dict(tags=bundle._properties._tags, attributes=dict( enabled=bundle._properties._attributes.enabled, @@ -302,9 +304,11 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): self.log("Response : {0}".format(response)) results.append(response) - except Exception as e: + except ResourceNotFoundError as ec: self.log("Did not find the key vault secret {0}: {1}".format( - self.name, str(e))) + self.name, str(ec))) + except Exception as ec2: + self.fail("Find the key vault secret got exception, exception as {0}".format(str(ec2))) return results def get_secret_versions(self): @@ -326,7 +330,7 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): if self.has_tags(item['tags'], self.tags): results.append(item) except Exception as e: - self.log("Did not find secret versions {0} : {1}.".format( + self.fail("Did not find secret versions {0} : {1}.".format( self.name, str(e))) return results @@ -349,7 +353,7 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): if self.has_tags(item['tags'], self.tags): results.append(item) except Exception as e: - self.log( + self.fail( "Did not find key vault in current subscription {0}.".format( str(e))) return results @@ -372,9 +376,12 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): self.log("Response : {0}".format(response)) results.append(response) - except Exception as e: + except ResourceNotFoundError as ec: self.log("Did not find the key vault secret {0}: {1}".format( - self.name, str(e))) + self.name, str(ec))) + except Exception as ec2: + self.fail("Did not find the key vault secret {0}: {1}".format( + self.name, str(ec2))) return results def list_deleted_secrets(self): @@ -396,7 +403,7 @@ class AzureRMKeyVaultSecretInfo(AzureRMModuleBase): if self.has_tags(item['tags'], self.tags): results.append(item) except Exception as e: - self.log( + self.fail( "Did not find key vault in current subscription {0}.".format( str(e))) return results diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_lock_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_lock_info.py index 39abbf3b7..0805cfa62 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_lock_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_lock_info.py @@ -158,7 +158,7 @@ class AzureRMLockInfo(AzureRMModuleBase): for key in self.module_arg_spec.keys(): setattr(self, key, kwargs[key]) - self._mgmt_client = self.get_mgmt_svc_client(GenericRestClient, is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) + self._mgmt_client = self.get_mgmt_svc_client(GenericRestClient, base_url=self._cloud_environment.endpoints.resource_manager) changed = False # construct scope id scope = self.get_scope() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk.py index 2b27fbbff..6f6443994 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_manageddisk.py @@ -491,12 +491,13 @@ class AzureRMManagedDisk(AzureRMModuleBase): # unmount from the old virtual machine and mount to the new virtual machine if self.managed_by or self.managed_by == '': vm_name = parse_resource_id(disk_instance.get('managed_by', '')).get('name') if disk_instance else None + resource_group = parse_resource_id(disk_instance.get('managed_by', '')).get('resource_group') if disk_instance else None vm_name = vm_name or '' if self.managed_by != vm_name or self.is_attach_caching_option_different(vm_name, result): changed = True if not self.check_mode: if vm_name: - self.detach(self.resource_group, vm_name, result) + self.detach(resource_group, vm_name, result) if self.managed_by: self.attach(self.resource_group, self.managed_by, result) result = self.get_managed_disk() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup.py index 35235ccbe..f4f03f121 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_managementgroup.py @@ -222,17 +222,16 @@ class Actions: class AzureRMManagementGroups(AzureRMModuleBaseExt): def __init__(self): self.module_arg_spec = dict( - group_id=dict(type='str', updatable=False, required=True), - name=dict(type='str', updatable=False), + group_id=dict(type='str', required=True), + name=dict(type='str'), id=dict(type='str'), type=dict(type='str'), properties=dict( type='dict', - disposition="/", options=dict( - tenant_id=dict(type='str', disposition="tenantId"), - display_name=dict(type='str', disposition="displayName"), - parent_id=dict(type='str', disposition="details/parent/id") + tenant_id=dict(type='str'), + display_name=dict(type='str'), + parent_id=dict(type='str') ) ), state=dict(type='str', default='present', choices=['present', 'absent']), @@ -260,16 +259,25 @@ class AzureRMManagementGroups(AzureRMModuleBaseExt): for key in list(self.module_arg_spec.keys()): if hasattr(self, key): setattr(self, key, kwargs[key]) + elif key == 'properties' and kwargs[key] is not None: + self.body['properties'] = {} + for item in kwargs['properties'].keys(): + if item == 'tenant_id': + self.body['properties']['tenantId'] = kwargs['properties'][item] + elif item == 'display_name': + self.body['properties']['displayName'] = kwargs['properties'][item] + elif item == 'parent_id': + self.body['properties']['details'] = {} + self.body['properties']['details']['parent'] = {} + self.body['properties']['details']['parent']['id'] = kwargs['properties'][item] + elif kwargs[key] is not None: self.body[key] = kwargs[key] - self.inflate_parameters(self.module_arg_spec, self.body, 0) - old_response = None response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) self.url = ('/providers' + @@ -293,13 +301,14 @@ class AzureRMManagementGroups(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.results['compare'] = [] - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - - if not self.default_compare(modifiers, self.body, old_response, '', self.results): - self.to_do = Actions.Update + for key in self.body.keys(): + if key == 'properties': + if old_response.get('properties') is None or \ + not all(self.body['properties'][item] == old_response['properties'].get(item) + for item in self.body['properties'].keys()): + self.to_do = Actions.Update + elif self.body[key] != old_response.get(key): + self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): self.log('Need to Create / Update the ManagementGroup instance') @@ -346,23 +355,34 @@ class AzureRMManagementGroups(AzureRMModuleBaseExt): # self.log('Creating / Updating the ManagementGroup instance {0}'.format(self.)) try: - response = self.mgmt_client.query(self.url, - 'PUT', - self.query_parameters, - self.header_parameters, - self.body, - self.status_code, - 600, - 30) + if self.to_do == Actions.Create: + response = self.mgmt_client.query(self.url, + 'PUT', + self.query_parameters, + self.header_parameters, + self.body, + self.status_code, + 600, + 30) + else: + response = self.mgmt_client.query(self.url, + 'PATCH', + self.query_parameters, + self.header_parameters, + self.body, + self.status_code, + 600, + 30) except Exception as exc: self.log('Error attempting to create the ManagementGroup instance.') self.fail('Error creating the ManagementGroup instance: {0}'.format(str(exc))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} - pass + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase.py index a8caa1745..e26ac2a96 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase.py @@ -92,7 +92,7 @@ import time try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from azure.core.exceptions import ResourceNotFoundError + from azure.core.exceptions import ResourceNotFoundError, HttpResponseError from azure.core.polling import LROPoller except ImportError: # This is handled in azure_rm_common @@ -282,6 +282,8 @@ class AzureRMMySqlDatabase(AzureRMModuleBase): self.log("MySQL Database instance : {0} found".format(response.name)) except ResourceNotFoundError as e: self.log('Did not find the MySQL Database instance.') + except HttpResponseError as e: + self.log("Get MySQL Database instance error. code: {0}, message: {1}".format(e.status_code, str(e.error))) if found is True: return response.as_dict() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase_info.py index db2cb8cdf..aef0f1df6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_mysqldatabase_info.py @@ -101,7 +101,7 @@ databases: try: from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase - from azure.core.exceptions import ResourceNotFoundError + from azure.core.exceptions import ResourceNotFoundError, HttpResponseError except ImportError: # This is handled in azure_rm_common pass @@ -159,6 +159,8 @@ class AzureRMMySqlDatabaseInfo(AzureRMModuleBase): self.log("Response : {0}".format(response)) except ResourceNotFoundError as e: self.log('Could not get facts for Databases.') + except HttpResponseError as e: + self.log("Get MySQL Database instance error. code: {0}, message: {1}".format(e.status_code, str(e.error))) if response is not None: results.append(self.format_item(response)) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface.py index bb17132d4..3343d5ac1 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface.py @@ -816,7 +816,7 @@ class AzureRMNetworkInterface(AzureRMModuleBase): if self.state == 'present': subnet = self.network_models.SubResource( id='/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/virtualNetworks/{2}/subnets/{3}'.format( - self.virtual_network['subscription_id'], + self.virtual_network['subscription'] if self.virtual_network.get('subscription') else self.virtual_network['subscription_id'], self.virtual_network['resource_group'], self.virtual_network['name'], self.subnet_name)) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface_info.py index deeb2c8c6..2a71473d6 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_networkinterface_info.py @@ -63,176 +63,214 @@ EXAMPLES = ''' ''' RETURN = ''' -azure_networkinterfaces: - description: - - List of network interface dicts. - returned: always - type: list - example: [{ - "dns_settings": { - "applied_dns_servers": [], - "dns_servers": [], - "internal_dns_name_label": null, - "internal_fqdn": null - }, - "enable_ip_forwarding": false, - "etag": 'W/"59726bfc-08c4-44ed-b900-f6a559876a9d"', - "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroup/myResourceGroup/providers/Microsoft.Network/networkInterfaces/nic003", - "ip_configuration": { - "name": "default", - "private_ip_address": "10.10.0.4", - "private_ip_allocation_method": "Dynamic", - "public_ip_address": { - "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroup/myResourceGroup/providers/Microsoft.Network/publicIPAddresses/publicip001", - "name": "publicip001" - }, - "subnet": { - "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroup/myResourceGroup/providers/Microsoft.Network/virtualNetworks/vnet001/subnets/subnet001", - "name": "subnet001", - "virtual_network_name": "vnet001" - } - }, - "location": "westus", - "mac_address": null, - "name": "nic003", - "network_security_group": { - "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroup/myResourceGroup/providers/Microsoft.Network/networkSecurityGroups/secgroup001", - "name": "secgroup001" - }, - "primary": null, - "provisioning_state": "Succeeded", - "tags": {}, - "type": "Microsoft.Network/networkInterfaces" - }] networkinterfaces: description: - List of network interface dicts. Each dict contains parameters can be passed to M(azure.azcollection.azure_rm_networkinterface) module. - type: list + type: complex returned: always contains: id: description: - Id of the network interface. type: str + returned: always + sample: "/subscriptions/xxxx-xxxxx/resourceGroups/testRG/providers/Microsoft.Network/networkInterfaces/nic01" resource_group: description: - Name of a resource group where the network interface exists. type: str + returned: always + sample: testRG name: description: - Name of the network interface. type: str + returned: always + sample: nic01 location: description: - Azure location. type: str + returned: always + sample: eastus virtual_network: description: - An existing virtual network with which the network interface will be associated. - It is a dict which contains I(name) and I(resource_group) of the virtual network. - type: raw + type: complex + returned: always + contains: + name: + description: + - The name of the virtual network relate network interface. + type: str + returned: always + sample: vnetnic01 + resource_gorup: + description: + - Resource groups name that exist on the virtual network. + type: str + returned: always + sample: testRG + subscription_id: + description: + - Virtual network Subscription ID. + type: str + returned: always + sample: xxxxxxx-xxxxxxxxxxxxx + subnet_id: + description: + - The subnet's ID. + type: str + returned: always + sample: "/subscriptions/xxx-xxxx/resourceGroups/testRG/providers/Microsoft.Network/virtualNetworks/nic01/subnets/sub01" subnet: description: - Name of an existing subnet within the specified virtual network. type: str + returned: always + sample: sub01 tags: description: - Tags of the network interface. type: dict + returned: always + sample: {key1: value1, key2: value2} ip_configurations: description: - List of IP configurations, if contains multiple configurations. type: complex + returned: always contains: name: description: - Name of the IP configuration. type: str + returned: always + sample: default private_ip_address: description: - Private IP address for the IP configuration. - type: list + type: str + returned: always + sample: 10.10.0.4 private_ip_allocation_method: description: - Private IP allocation method. type: str + returned: always + sample: Dynamic public_ip_address: description: - Name of the public IP address. None for disable IP address. type: str + returned: always + sample: null public_ip_allocation_method: description: - Public IP allocation method. type: str + returned: always + sample: null load_balancer_backend_address_pools: description: - List of existing load-balancer backend address pools associated with the network interface. type: list + returned: always + sample: null application_gateway_backend_address_pools: description: - List of existing application gateway backend address pools associated with the network interface. version_added: "1.10.0" type: list + returned: always + sample: null primary: description: - Whether the IP configuration is the primary one in the list. type: bool + returned: always + sample: true application_security_groups: description: - List of Application security groups. type: list + returned: always sample: ['/subscriptions/<subsid>/resourceGroups/<rg>/providers/Microsoft.Network/applicationSecurityGroups/myASG'] enable_accelerated_networking: description: - Specifies whether the network interface should be created with the accelerated networking feature or not. type: bool + returned: always + sample: false create_with_security_group: description: - Specifies whether a default security group should be be created with the NIC. Only applies when creating a new NIC. type: bool + returned: always + sample: false security_group: description: - A security group resource ID with which to associate the network interface. type: str + returned: always + sample: null enable_ip_forwarding: description: - Whether to enable IP forwarding type: bool + returned: always + sample: false dns_servers: description: - Which DNS servers should the NIC lookup. - List of IP addresses. type: list + returned: always + sample: [] mac_address: description: - The MAC address of the network interface. type: str + returned: always + sample: null provisioning_state: description: - The provisioning state of the network interface. type: str + returned: always + sample: Succeeded dns_settings: description: - The DNS settings in network interface. type: complex + returned: always contains: dns_servers: description: - List of DNS servers IP addresses. type: list + returned: always + sample: [] applied_dns_servers: description: - If the VM that uses this NIC is part of an Availability Set, then this list will have the union of all DNS servers from all NICs that are part of the Availability Set. This property is what is configured on each of those VMs. type: list + returned: always + sample: [] internal_dns_name_label: description: - Relative DNS name for this NIC used for internal communications between VMs in the same virtual network. type: str + returned: always + sample: null internal_fqdn: description: - Fully qualified DNS name supporting internal communications between VMs in the same virtual network. type: str + returned: always + sample: null ''' # NOQA try: from azure.core.exceptions import ResourceNotFoundError @@ -268,6 +306,8 @@ def nic_to_dict(nic): subnet = subnet_dict.get('subnets') if subnet_dict else None virtual_network = dict( resource_group=subnet_dict.get('resourceGroups'), + subnet_id=config.subnet.id if config and config.subnet else None, + subscription_id=subnet_dict.get('subscriptions'), name=subnet_dict.get('virtualNetworks')) if subnet_dict else None return dict( id=nic.id, diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster.py index cc579c998..b0c28a190 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster.py @@ -412,86 +412,57 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): self.module_arg_spec = dict( resource_group=dict( type='str', - updatable=False, - disposition='resourceGroupName', required=True ), name=dict( type='str', - updatable=False, - disposition='resourceName', required=True ), location=dict( type='str', - updatable=False, - required=True, - disposition='/' + required=True ), cluster_profile=dict( type='dict', - disposition='/properties/clusterProfile', default=dict(), options=dict( pull_secret=dict( type='str', no_log=True, - updatable=False, - disposition='pullSecret', - purgeIfNone=True ), cluster_resource_group_id=dict( type='str', - updatable=False, - disposition='resourceGroupId', - purgeIfNone=True ), domain=dict( type='str', - updatable=False, - disposition='domain', - purgeIfNone=True ), version=dict( type='str', - updatable=False, - disposition='version', - purgeIfNone=True ) ), ), service_principal_profile=dict( type='dict', - disposition='/properties/servicePrincipalProfile', options=dict( client_id=dict( type='str', - updatable=False, - disposition='clientId', required=True ), client_secret=dict( type='str', no_log=True, - updatable=False, - disposition='clientSecret', required=True ) ) ), network_profile=dict( type='dict', - disposition='/properties/networkProfile', options=dict( pod_cidr=dict( type='str', - updatable=False, - disposition='podCidr' ), service_cidr=dict( type='str', - updatable=False, - disposition='serviceCidr' ) ), default=dict( @@ -501,21 +472,15 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): ), master_profile=dict( type='dict', - disposition='/properties/masterProfile', options=dict( vm_size=dict( type='str', - updatable=False, - disposition='vmSize', choices=['Standard_D8s_v3', 'Standard_D16s_v3', 'Standard_D32s_v3'], - purgeIfNone=True ), subnet_id=dict( type='str', - updatable=False, - disposition='subnetId', required=True ) ) @@ -523,94 +488,66 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): worker_profiles=dict( type='list', elements='dict', - disposition='/properties/workerProfiles', options=dict( name=dict( type='str', - disposition='name', - updatable=False, required=True, choices=['worker'] ), count=dict( type='int', - disposition='count', - updatable=False, - purgeIfNone=True ), vm_size=dict( type='str', - disposition='vmSize', - updatable=False, choices=['Standard_D4s_v3', 'Standard_D8s_v3'], - purgeIfNone=True ), subnet_id=dict( type='str', - disposition='subnetId', - updatable=False, required=True ), disk_size=dict( type='int', - disposition='diskSizeGB', - updatable=False, - purgeIfNone=True ) ) ), api_server_profile=dict( type='dict', - disposition='/properties/apiserverProfile', options=dict( visibility=dict( type='str', - disposition='visibility', choices=['Public', 'Private'], default='Public' ), url=dict( type='str', - disposition='*', - updatable=False ), ip=dict( type='str', - disposition='*', - updatable=False ) ) ), ingress_profiles=dict( type='list', elements='dict', - disposition='/properties/ingressProfiles', options=dict( name=dict( type='str', - disposition='name', - updatable=False, choices=['default'], default='default' ), visibility=dict( type='str', - disposition='visibility', - updatable=False, choices=['Public', 'Private'], default='Public' ), ip=dict( type='str', - disposition='*', - updatable=False ) ) ), provisioning_state=dict( type='str', - disposition='/properties/provisioningState' ), state=dict( type='str', @@ -630,6 +567,7 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): self.to_do = Actions.NoAction self.body = {} + self.body['properties'] = {} self.query_parameters = {} self.header_parameters = {} @@ -645,13 +583,58 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: - self.body[key] = kwargs[key] + if key == 'cluster_profile': + self.body['properties']['clusterProfile'] = {} + for item in ['pull_secret', 'cluster_resource_group_id', 'domain', 'version']: + if item == 'pull_secret': + self.body['properties']['clusterProfile']['pullSecret'] = kwargs[key].get(item) + elif item == 'cluster_resource_group_id': + self.body['properties']['clusterProfile']['resourceGroupId'] = kwargs[key].get(item) + elif item == 'domain': + self.body['properties']['clusterProfile']['domain'] = kwargs[key].get(item) + elif item == 'version': + self.body['properties']['clusterProfile']['version'] = kwargs[key].get(item) + elif key == 'service_principal_profile': + self.body['properties']['servicePrincipalProfile'] = {} + self.body['properties']['servicePrincipalProfile']['ClientId'] = kwargs[key].get('client_id') + self.body['properties']['servicePrincipalProfile']['clientSecret'] = kwargs[key].get('client_secret') + elif key == 'network_profile': + self.body['properties']['networkProfile'] = {} + for item in kwargs[key].keys(): + if item == 'pod_cidr': + self.body['properties']['networkProfile']['podCidr'] = kwargs[key].get(item) + elif item == 'service_cidr': + self.body['properties']['networkProfile']['serviceCidr'] = kwargs[key].get(item) + elif key == 'master_profile': + self.body['properties']['masterProfile'] = {} + if 'subnet_id' in kwargs[key].keys(): + self.body['properties']['masterProfile']['subnetId'] = kwargs[key].get('subnet_id') + self.body['properties']['masterProfile']['vmSize'] = kwargs[key].get('vm_size') + elif key == 'worker_profiles': + self.body['properties']['workerProfiles'] = [] + for item in kwargs[key]: + worker_profile = {} + if item.get('name') is not None: + worker_profile['name'] = item['name'] + if item.get('subnet_id') is not None: + worker_profile['subnetId'] = item['subnet_id'] + worker_profile['count'] = item.get('count') + worker_profile['vmSize'] = item.get('vm_size') + worker_profile['diskSizeGB'] = item.get('disk_size') + + self.body['properties']['workerProfiles'].append(worker_profile) + elif key == 'api_server_profile': + self.body['properties']['apiserverProfile'] = kwargs[key] + elif key == 'ingress_profiles': + self.body['properties']['ingressProfiles'] = kwargs[key] + elif key == 'provisioning_state': + self.body['properties']['provisioningState'] = kwargs[key] + else: + self.body[key] = kwargs[key] - self.inflate_parameters(self.module_arg_spec, self.body, 0) response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) self.url = ('/subscriptions' + @@ -756,11 +739,12 @@ class AzureRMOpenShiftManagedClusters(AzureRMModuleBaseExt): self.log('Error attempting to create the OpenShiftManagedCluster instance.') self.fail('Error creating the OpenShiftManagedCluster instance: {0}' '\n{1}'.format(str(self.body), str(exc))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} - pass + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster_info.py index ed359c641..cbda2da8b 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedcluster_info.py @@ -254,7 +254,6 @@ class AzureRMOpenShiftManagedClustersInfo(AzureRMModuleBaseExt): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if (self.resource_group is not None and self.name is not None): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedclusterkubeconfig_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedclusterkubeconfig_info.py new file mode 100644 index 000000000..5b5f73a29 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_openshiftmanagedclusterkubeconfig_info.py @@ -0,0 +1,227 @@ +#!/usr/bin/python +# +# Copyright (c) 2020 Haiyuan Zhang <haiyzhan@micosoft.com> +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_openshiftmanagedclusterkubeconfig_info +version_added: '1.17.0' +short_description: Get admin kubeconfig of Azure Red Hat OpenShift Managed Cluster +description: + - get kubeconfig of Azure Red Hat OpenShift Managed Cluster instance. +options: + resource_group: + description: + - The name of the resource group. + required: true + type: str + name: + description: + - Resource name. + required: true + type: str + path: + description: + - Destination filepath of kubeconfig file + required: false + type: str +extends_documentation_fragment: + - azure.azcollection.azure +author: + - Maxim Babushkin (@maxbab) +''' + +EXAMPLES = ''' +- name: Obtain kubeconfig file of ARO cluster + azure_rm_openshiftmanagedclusterkubeconfig_info: + name: myCluster + resource_group: myResourceGroup + register: kubeconf + +- name: Print registered kubeconfig file + debug: + msg: "{{ kubeconf['kubeconfig'] }}" + +- name: Fetch kubeconfig and save it as mycluster_kubeconfig filename + azure_rm_openshiftmanagedclusterkubeconfig_info: + name: myCluster + resource_group: myResourceGroup + path: ./files/mycluster_kubeconfig + +- name: Fetch kubeconfig and save it to specified directory (file will be named as kubeconfig by default) + azure_rm_openshiftmanagedclusterkubeconfig_info: + name: myCluster + resource_group: myResourceGroup + path: ./files/ +''' + +RETURN = ''' +kubeconfig: + description: + - kubeconfig value + returned: always + type: str +''' + +import base64 +import filecmp +import json +import os +import tempfile +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_ext import AzureRMModuleBaseExt +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common_rest import GenericRestClient + + +class Actions: + NoAction, Create, Update, Delete = range(4) + + +class AzureRMOpenShiftManagedClustersKubeconfigInfo(AzureRMModuleBaseExt): + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + type='str', required=True + ), + name=dict( + type='str', required=True + ), + path=dict( + type='str', required=False + ) + ) + + self.resource_group = None + self.name = None + self.path = None + + self.results = dict(changed=False) + self.mgmt_client = None + self.state = None + self.url = None + self.status_code = [200] + + self.query_parameters = {} + self.query_parameters['api-version'] = '2021-09-01-preview' + self.header_parameters = {} + self.header_parameters['Content-Type'] = 'application/json; charset=utf-8' + + self.mgmt_client = None + super(AzureRMOpenShiftManagedClustersKubeconfigInfo, self).__init__(self.module_arg_spec, supports_check_mode=True, supports_tags=False) + + def exec_module(self, **kwargs): + + for key in self.module_arg_spec: + setattr(self, key, kwargs[key]) + + self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, is_track2=True, + base_url=self._cloud_environment.endpoints.resource_manager) + self.results = self.get_kubeconfig() + if self.path and self.path_is_valid(): + self.write_kubeconfig_to_file() + return self.results + + def get_kubeconfig(self): + response = None + results = {} + # prepare url + self.url = ('/subscriptions' + + '/{{ subscription_id }}' + + '/resourceGroups' + + '/{{ resource_group }}' + + '/providers' + + '/Microsoft.RedHatOpenShift' + + '/openShiftClusters' + + '/{{ cluster_name }}' + + '/listAdminCredentials') + self.url = self.url.replace('{{ subscription_id }}', self.subscription_id) + self.url = self.url.replace('{{ resource_group }}', self.resource_group) + self.url = self.url.replace('{{ cluster_name }}', self.name) + self.log("Fetch for kubeconfig from the cluster.") + try: + response = self.mgmt_client.query(self.url, + 'POST', + self.query_parameters, + self.header_parameters, + None, + self.status_code, + 600, + 30) + results = json.loads(response.body()) + except Exception as e: + self.log('Could not get info for @(Model.ModuleOperationNameUpper).') + return self.format_item(results) + + def format_item(self, item): + d = { + 'kubeconfig': item.get('kubeconfig'), + } + return d + + def path_is_valid(self): + if not os.path.basename(self.path): + if os.path.isdir(self.path): + self.log("Path is dir. Appending file name.") + self.path += "kubeconfig" + else: + try: + self.log('Attempting to makedirs {0}'.format(self.path)) + os.makedirs(self.path) + except IOError as exc: + self.fail("Failed to create directory {0} - {1}".format(self.path, str(exc))) + self.path += "kubeconfig" + else: + file_name = os.path.basename(self.path) + path = self.path.replace(file_name, '') + self.log('Checking path {0}'. format(path)) + # If the "path" is not defined, it's cwd. + if path and not os.path.isdir(path): + try: + self.log('Attempting to makedirs {0}'. format(path)) + os.makedirs(path) + except IOError as exc: + self.fail("Failed to create directory {0} - {1}".format(path, str(exc))) + self.log("Validated path - {0}". format(self.path)) + return True + + def write_kubeconfig_to_file(self): + decoded_bytes = base64.b64decode(self.results['kubeconfig']) + decoded_string = decoded_bytes.decode("utf-8") + + if os.path.exists(self.path): + self.log('Existing kubeconfig file found. Compare, to decide if needs to override') + # If kubeconfig file already exists, compare it with the new file + # If equal, do nothing, otherwise, override. + tmp_kubeconfig = tempfile.TemporaryFile(mode='w') + tmp_kubeconfig.write(decoded_string) + tmp_kubeconfig.seek(0) + + # No need to close the temp file as it's closed by filecmp.cmp. + if filecmp.cmp(tmp_kubeconfig.name, self.path): + self.log("Files are identical. No need to override.") + self.results['changed'] = False + return + + self.log("Create {0} kubeconfig file.".format(self.path)) + try: + with open(self.path, "w") as file: + file.write(decoded_string) + except Exception as exc: + self.fail("Failed to write kubeconfig output to file - {0} to {1} - {2}".format(self.results['kubeconfig'], + self.path, exc)) + self.log("The {0} kubeconfig file has been created.") + self.results['changed'] = True + return + + +def main(): + AzureRMOpenShiftManagedClustersKubeconfigInfo() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibleconfiguration_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibleconfiguration_info.py new file mode 100644 index 000000000..52810303b --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibleconfiguration_info.py @@ -0,0 +1,210 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_postgresqlflexibleconfiguration_info +version_added: "2.2.0" +short_description: Get Azure PostgreSQL Flexible Configuration facts +description: + - Get facts of Azure PostgreSQL Flexible Configuration. + +options: + resource_group: + description: + - The name of the resource group that contains the resource. + required: True + type: str + server_name: + description: + - The name of the server. + required: True + type: str + name: + description: + - Setting name. + type: str + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: Get specific setting of PostgreSQL configuration + azure_rm_postgresqlflexibleconfiguration_info: + resource_group: myResourceGroup + server_name: testpostgresqlserver + name: deadlock_timeout + +- name: Get all settings of PostgreSQL Flexible Configuration + azure_rm_postgresqlflexibleconfiguration_info: + resource_group: myResourceGroup + server_name: testpostgresqlserver +''' + +RETURN = ''' +settings: + description: + - A list of dictionaries containing MySQL Server settings. + returned: always + type: complex + contains: + id: + description: + - Setting resource ID. + returned: always + type: str + sample: "/subscriptions/xxx-xxx/resourceGroups/testRG/providers/Microsoft.DBforPostgreSQL/flexibleServers/post2/configurations/xmloption" + name: + description: + - Setting name. + returned: always + type: str + sample: deadlock_timeout + server_name: + description: + - The name of the post gresql flexible server. + type: str + returned: always + sample: post2 + resource_group: + description: + - Name of the server's resource group. + type: str + returned: always + sample: testRG + value: + description: + - Setting value. + returned: always + type: raw + sample: 1000 + description: + description: + - Description of the configuration. + returned: always + type: str + sample: Deadlock timeout. + source: + description: + - Source of the configuration. + returned: always + type: str + sample: system-default +''' + +try: + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + from azure.core.exceptions import ResourceNotFoundError +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMPostgreSQLFlexibleConfigurationInfo(AzureRMModuleBase): + def __init__(self): + # define user inputs into argument + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + server_name=dict( + type='str', + required=True + ), + name=dict( + type='str' + ) + ) + # store the results of the module operation + self.results = dict( + changed=False + ) + self.resource_group = None + self.server_name = None + self.name = None + super(AzureRMPostgreSQLFlexibleConfigurationInfo, self).__init__(self.module_arg_spec, supports_check_mode=True, supports_tags=False) + + def exec_module(self, **kwargs): + for key in self.module_arg_spec: + setattr(self, key, kwargs[key]) + + if self.name is not None: + self.results['settings'] = self.get() + else: + self.results['settings'] = self.list_by_server() + return self.results + + def get(self): + ''' + Gets facts of the specified PostgreSQL Flexible Configuration. + + :return: deserialized PostgreSQL Flexible Configurationinstance state dictionary + ''' + response = None + try: + response = self.postgresql_flexible_client.configurations.get(resource_group_name=self.resource_group, + server_name=self.server_name, + configuration_name=self.name) + self.log("Response : {0}".format(response)) + except ResourceNotFoundError as e: + self.log('Could not get requested setting, Exception as {0}'.format(e)) + return [] + + return [self.format_item(response)] + + def list_by_server(self): + ''' + Gets facts of the specified PostgreSQL Flexible Configuration. + + :return: deserialized PostgreSQL Flexible Configurationinstance state dictionary + ''' + response = None + results = [] + try: + response = self.postgresql_flexible_client.configurations.list_by_server(resource_group_name=self.resource_group, + server_name=self.server_name) + self.log("Response : {0}".format(response)) + except Exception as e: + self.log('List the flexible server config get exception, except as {0}'.format(e)) + return [] + + if response is not None: + for item in response: + results.append(self.format_item(item)) + + return results + + def format_item(self, item): + d = item.as_dict() + d = { + 'resource_group': self.resource_group, + 'server_name': self.server_name, + 'id': d['id'], + 'name': d['name'], + 'value': d['value'], + 'description': d['description'], + 'source': d['source'] + } + return d + + +def main(): + AzureRMPostgreSQLFlexibleConfigurationInfo() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibledatabase.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibledatabase.py new file mode 100644 index 000000000..0656ddac6 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibledatabase.py @@ -0,0 +1,288 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_postgresqlflexibledatabase +version_added: "2.2.0" +short_description: Manage PostgreSQL Flexible Database instance +description: + - Create, update and delete instance of PostgreSQL Flexible Database. + +options: + resource_group: + description: + - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. + required: True + type: str + server_name: + description: + - The name of the server. + required: True + type: str + name: + description: + - The name of the database. + required: True + type: str + charset: + description: + - The charset of the database. + type: str + collation: + description: + - The collation of the database. + type: str + state: + description: + - Assert the state of the PostgreSQL Flexible database. Use C(present) to create or update a database and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: Create (or update) PostgreSQL Flexible Database + azure_rm_postgresqlflexibledatabase: + resource_group: myResourceGroup + server_name: testserver + name: db1 + charset: UTF8 + collation: en_US.utf8 + +- name: Delete PostgreSQL Flexible Database + azure_rm_postgresqlflexibledatabase: + resource_group: myResourceGroup + server_name: testserver + name: db1 +''' + +RETURN = ''' +database: + description: + - A list of dictionaries containing facts for PostgreSQL Flexible Database. + returned: always + type: complex + contains: + id: + description: + - Resource ID of the postgresql flexible database. + returned: always + type: str + sample: "/subscriptions/xxx-xxx/resourceGroups/testRG/providers/Microsoft.DBforPostgreSQL/flexibleServers/postfle9/databases/freddatabase" + name: + description: + - Resource name. + returned: always + type: str + sample: freddatabase + charset: + description: + - The charset of the database. + returned: always + type: str + sample: UTF-8 + collation: + description: + - The collation of the database. + returned: always + type: str + sample: en_US.utf8 + type: + description: + - The type of the resource. + returned: always + type: str + sample: Microsoft.DBforPostgreSQL/flexibleServers/databases +''' + + +try: + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + from azure.core.exceptions import ResourceNotFoundError + from azure.core.polling import LROPoller +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMPostgreSqlFlexibleDatabases(AzureRMModuleBase): + """Configuration class for an Azure RM PostgreSQL Flexible Database resource""" + + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + server_name=dict( + type='str', + required=True + ), + name=dict( + type='str', + required=True + ), + charset=dict( + type='str' + ), + collation=dict( + type='str' + ), + state=dict( + type='str', + default='present', + choices=['present', 'absent'] + ) + ) + + self.resource_group = None + self.server_name = None + self.name = None + self.parameters = dict() + + self.results = dict(changed=False) + self.state = None + + super(AzureRMPostgreSqlFlexibleDatabases, self).__init__(derived_arg_spec=self.module_arg_spec, + supports_check_mode=True, + supports_tags=False) + + def exec_module(self, **kwargs): + """Main module execution method""" + + for key in list(self.module_arg_spec.keys()): + if hasattr(self, key): + setattr(self, key, kwargs[key]) + elif kwargs[key] is not None: + if key == "charset": + self.parameters["charset"] = kwargs[key] + elif key == "collation": + self.parameters["collation"] = kwargs[key] + + old_response = None + response = None + changed = False + + old_response = self.get_postgresqlflexibledatabase() + + if not old_response: + self.log("PostgreSQL Flexible Database instance doesn't exist") + if self.state == 'absent': + self.log("Old instance didn't exist") + else: + changed = True + if not self.check_mode: + response = self.create_update_postgresqlflexibledatabase(self.parameters) + else: + self.log("PostgreSQL Flexible Database instance already exists") + if self.state == 'absent': + changed = True + if not self.check_mode: + response = self.delete_postgresqlflexibledatabase() + else: + if (self.parameters.get('charset') is not None and self.parameters['charset'] != old_response['charset']) or\ + (self.parameters.get('collation') is not None and self.parameters['collation'] != old_response['collation']): + changed = True + if not self.check_mode: + self.fail("The Post Gresql Flexible database not support to update") + else: + response = old_response + + self.results['database'] = response + self.results['changed'] = changed + return self.results + + def create_update_postgresqlflexibledatabase(self, body): + ''' + Creates or updates PostgreSQL Flexible Database with the specified configuration. + + :return: deserialized PostgreSQL Flexible Database instance state dictionary + ''' + self.log("Creating / Updating the PostgreSQL Flexible Database instance {0}".format(self.name)) + + try: + response = self.postgresql_flexible_client.databases.begin_create(resource_group_name=self.resource_group, + server_name=self.server_name, + database_name=self.name, + parameters=body) + if isinstance(response, LROPoller): + response = self.get_poller_result(response) + + except Exception as exc: + self.log('Error attempting to create the PostgreSQL Flexible Database instance.') + self.fail("Error creating the PostgreSQL Flexible Database instance: {0}".format(str(exc))) + return self.format_item(response) + + def delete_postgresqlflexibledatabase(self): + ''' + Deletes specified PostgreSQL Flexible Database instance in the specified subscription and resource group. + + :return: True + ''' + self.log("Deleting the PostgreSQL Flexible Database instance {0}".format(self.name)) + try: + self.postgresql_flexible_client.databases.begin_delete(resource_group_name=self.resource_group, + server_name=self.server_name, + database_name=self.name) + except Exception as ec: + self.log('Error attempting to delete the PostgreSQL Flexible Database instance.') + self.fail("Error deleting the PostgreSQL Flexible Database instance: {0}".format(str(ec))) + + def get_postgresqlflexibledatabase(self): + ''' + Gets the properties of the specified PostgreSQL Flexible Database. + + :return: deserialized PostgreSQL Flexible Database instance state dictionary + ''' + self.log("Checking if the PostgreSQL Flexible Database instance {0} is present".format(self.name)) + found = False + try: + response = self.postgresql_flexible_client.databases.get(resource_group_name=self.resource_group, + server_name=self.server_name, + database_name=self.name) + found = True + self.log("Response : {0}".format(response)) + self.log("PostgreSQL Flexible Database instance : {0} found".format(response.name)) + except ResourceNotFoundError as e: + self.log('Did not find the PostgreSQL Flexible Database instance. Exception as {0}'.format(e)) + if found is True: + return self.format_item(response) + + return None + + def format_item(self, item): + result = dict( + id=item.id, + name=item.name, + type=item.type, + charset=item.charset, + collation=item.collation + ) + return result + + +def main(): + """Main execution""" + AzureRMPostgreSqlFlexibleDatabases() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibledatabase_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibledatabase_info.py new file mode 100644 index 000000000..545baf53f --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibledatabase_info.py @@ -0,0 +1,239 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_postgresqlflexibledatabase_info +version_added: "2.2.0" +short_description: Get Azure PostgreSQL Flexible Database facts +description: + - Get facts of PostgreSQL Flexible Database. + +options: + resource_group: + description: + - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. + type: str + required: True + server_name: + description: + - The name of the post gresql server. + type: str + required: True + name: + description: + - The name of the post gresql database. + type: str + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: List instance of PostgreSQL Flexible Database by server name + azure_rm_postgresqlflexibledatabase_info: + resource_group: myResourceGroup + server_name: server_name + +- name: Get instances of PostgreSQL Flexible Database + azure_rm_postgresqlflexibledatabase_info: + resource_group: myResourceGroup + server_name: server_name + name: database_name +''' + +RETURN = ''' +database: + description: + - A list of dictionaries containing facts for PostgreSQL Flexible Database. + returned: always + type: complex + contains: + id: + description: + - Resource ID of the postgresql flexible database. + returned: always + type: str + sample: "/subscriptions/xxx-xxx/resourceGroups/testRG/providers/Microsoft.DBforPostgreSQL/flexibleServers/postfle9/databases/freddatabase" + name: + description: + - Resource name. + returned: always + type: str + sample: freddatabase + charset: + description: + - The charset of the database. + returned: always + type: str + sample: UTF-8 + collation: + description: + - The collation of the database. + returned: always + type: str + sample: en_US.utf8 + type: + description: + - The type of the resource. + returned: always + type: str + sample: Microsoft.DBforPostgreSQL/flexibleServers/databases + system_data: + description: + - The system metadata relating to this resource. + type: complex + returned: always + contains: + created_by: + description: + - The identity that created the resource. + type: str + returned: always + sample: null + created_by_type: + description: + - The type of identity that created the resource. + returned: always + type: str + sample: null + created_at: + description: + - The timestamp of resource creation (UTC). + returned: always + sample: null + type: str + last_modified_by: + description: + - The identity that last modified the resource. + type: str + returned: always + sample: null + last_modified_by_type: + description: + - The type of identity that last modified the resource. + returned: always + sample: null + type: str + last_modified_at: + description: + - The timestamp of resource last modification (UTC). + returned: always + sample: null + type: str +''' + + +try: + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + from azure.core.exceptions import ResourceNotFoundError +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMPostgreSqlFlexibleDatabaseInfo(AzureRMModuleBase): + def __init__(self): + # define user inputs into argument + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + server_name=dict( + type='str', + required=True + ), + name=dict( + type='str' + ), + ) + # store the results of the module operation + self.results = dict( + changed=False + ) + self.resource_group = None + self.name = None + self.server_name = None + super(AzureRMPostgreSqlFlexibleDatabaseInfo, self).__init__(self.module_arg_spec, supports_check_mode=True, supports_tags=False, facts_module=True) + + def exec_module(self, **kwargs): + for key in self.module_arg_spec: + setattr(self, key, kwargs[key]) + + if self.name is not None: + self.results['databases'] = self.get() + else: + self.results['databases'] = self.list_all() + return self.results + + def get(self): + response = None + results = [] + try: + response = self.postgresql_flexible_client.databases.get(resource_group_name=self.resource_group, + server_name=self.server_name, + database_name=self.name) + self.log("Response : {0}".format(response)) + except ResourceNotFoundError: + self.log('Could not get facts for PostgreSQL Flexible Server.') + + if response is not None: + results.append(self.format_item(response)) + + return results + + def list_all(self): + response = None + results = [] + try: + response = self.postgresql_flexible_client.databases.list_by_server(resource_group_name=self.resource_group, + server_name=self.server_name) + self.log("Response : {0}".format(response)) + except Exception as ec: + self.log('Could not get facts for PostgreSQL Flexible Servers.') + + if response is not None: + for item in response: + results.append(self.format_item(item)) + + return results + + def format_item(self, item): + result = dict( + id=item.id, + name=item.name, + system_data=dict(), + type=item.type, + charset=item.charset, + collation=item.collation + ) + if item.system_data is not None: + result['system_data']['created_by'] = item.system_data.created_by + result['system_data']['created_by_type'] = item.system_data.created_by_type + result['system_data']['created_at'] = item.system_data.created_at + result['system_data']['last_modified_by'] = item.system_data.last_modified_by + result['system_data']['last_modified_by_type'] = item.system_data.last_modified_by_type + result['system_data']['last_modified_at'] = item.system_data.last_modified_at + + return result + + +def main(): + AzureRMPostgreSqlFlexibleDatabaseInfo() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexiblefirewallrule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexiblefirewallrule.py new file mode 100644 index 000000000..c73843c46 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexiblefirewallrule.py @@ -0,0 +1,294 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_postgresqlflexiblefirewallrule +version_added: "2.2.0" +short_description: Manage PostgreSQL flexible firewall rule instance +description: + - Create, update and delete instance of PostgreSQL flexible firewall rule. + +options: + resource_group: + description: + - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. + required: True + type: str + server_name: + description: + - The name of the server. + required: True + type: str + name: + description: + - The name of the PostgreSQL flexible firewall rule. + required: True + type: str + start_ip_address: + description: + - The start IP address of the PostgreSQL flexible firewall rule. Must be IPv4 format. + type: str + end_ip_address: + description: + - The end IP address of the PostgreSQL flexible firewall rule. Must be IPv4 format. + type: str + state: + description: + - Assert the state of the PostgreSQL flexible firewall rule. + - Use C(present) to create or update a PostgreSQL flexible firewall rule and C(absent) to delete it. + default: present + type: str + choices: + - absent + - present + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: Create (or update) PostgreSQL flexible firewall rule + azure_rm_postgresqlflexiblefirewallrule: + resource_group: myResourceGroup + server_name: testserver + name: rule1 + start_ip_address: 10.0.0.16 + end_ip_address: 10.0.0.18 +''' + +RETURN = ''' +rules: + description: + - A list of dictionaries containing facts for PostgreSQL Flexible Firewall Rule. + returned: always + type: complex + contains: + id: + description: + - Resource ID. + returned: always + type: str + sample: "/subscriptions/xxx-xxx/resourceGroups/testRG/providers/Microsoft.DBforPostgreSQL/flexibleServers/flexibled9b/firewallRules/firewalld9b" + server_name: + description: + - The name of the server. + returned: always + type: str + sample: testserver + name: + description: + - Resource name. + returned: always + type: str + sample: rule1 + start_ip_address: + description: + - The start IP address of the PostgreSQL firewall rule. + returned: always + type: str + sample: 10.0.0.16 + end_ip_address: + description: + - The end IP address of the PostgreSQL firewall rule. + returned: always + type: str + sample: 10.0.0.18 +''' + + +try: + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + from azure.core.exceptions import ResourceNotFoundError + from azure.core.polling import LROPoller + import logging + logging.basicConfig(filename='log.log', level=logging.INFO) +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMPostgreSqlFlexibleFirewallRules(AzureRMModuleBase): + """Configuration class for an Azure RM PostgreSQL flexible firewall rule resource""" + + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + server_name=dict( + type='str', + required=True + ), + name=dict( + type='str', + required=True + ), + start_ip_address=dict( + type='str' + ), + end_ip_address=dict( + type='str' + ), + state=dict( + type='str', + default='present', + choices=['present', 'absent'] + ) + ) + + self.resource_group = None + self.server_name = None + self.name = None + self.start_ip_address = None + self.end_ip_address = None + + self.results = dict(changed=False) + self.state = None + self.parameters = dict() + + super(AzureRMPostgreSqlFlexibleFirewallRules, self).__init__(derived_arg_spec=self.module_arg_spec, + supports_check_mode=True, + supports_tags=False) + + def exec_module(self, **kwargs): + """Main module execution method""" + for key in list(self.module_arg_spec.keys()): + if hasattr(self, key): + setattr(self, key, kwargs[key]) + if key in ['start_ip_address', 'end_ip_address']: + self.parameters[key] = kwargs[key] + + old_response = None + response = None + changed = False + + old_response = self.get_firewallrule() + + if old_response is None: + self.log("PostgreSQL flexible firewall rule instance doesn't exist") + if self.state == 'absent': + self.log("Old instance didn't exist") + else: + changed = True + if not self.check_mode: + response = self.create_update_firewallrule(self.parameters) + else: + self.log("PostgreSQL flexible firewall rule instance already exists") + if self.state == 'absent': + changed = True + if self.check_mode: + response = old_response + else: + response = self.delete_firewallrule() + else: + self.log("Need to check if PostgreSQL flexible firewall rule instance has to be deleted or may be updated") + if (self.start_ip_address is not None) and (self.start_ip_address != old_response['start_ip_address']): + changed = True + else: + self.parameters['start_ip_address'] = old_response['start_ip_address'] + if (self.end_ip_address is not None) and (self.end_ip_address != old_response['end_ip_address']): + changed = True + else: + self.parameters['end_ip_address'] = old_response['end_ip_address'] + if changed: + if not self.check_mode: + response = self.create_update_firewallrule(self.parameters) + else: + response = old_response + else: + response = old_response + self.results['firewall_rule'] = response + self.results['changed'] = changed + + return self.results + + def create_update_firewallrule(self, body): + ''' + Creates or updates PostgreSQL flexible firewall rule with the specified configuration. + + :return: deserialized PostgreSQL flexible firewall rule instance state dictionary + ''' + self.log("Creating / Updating the PostgreSQL flexible firewall rule instance {0}".format(self.name)) + + try: + response = self.postgresql_flexible_client.firewall_rules.begin_create_or_update(resource_group_name=self.resource_group, + server_name=self.server_name, + firewall_rule_name=self.name, + parameters=body) + if isinstance(response, LROPoller): + response = self.get_poller_result(response) + + except Exception as exc: + self.log('Error attempting to create the PostgreSQL flexible firewall rule instance.') + self.fail("Error creating the PostgreSQL flexible firewall rule instance: {0}".format(str(exc))) + return self.format_item(response) + + def delete_firewallrule(self): + ''' + Deletes specified PostgreSQL flexible firewall rule instance in the specified subscription and resource group. + + :return: True + ''' + self.log("Deleting the PostgreSQL flexible firewall rule instance {0}".format(self.name)) + try: + self.postgresql_flexible_client.firewall_rules.begin_delete(resource_group_name=self.resource_group, + server_name=self.server_name, + firewall_rule_name=self.name) + except Exception as e: + self.log('Error attempting to delete the PostgreSQL flexible firewall rule instance.') + self.fail("Error deleting the PostgreSQL flexible firewall rule instance: {0}".format(str(e))) + + return True + + def get_firewallrule(self): + ''' + Gets the properties of the specified PostgreSQL flexible firewall rule. + + :return: deserialized PostgreSQL flexible firewall rule instance state dictionary + ''' + self.log("Checking if the PostgreSQL flexible firewall rule instance {0} is present".format(self.name)) + try: + response = self.postgresql_flexible_client.firewall_rules.get(resource_group_name=self.resource_group, + server_name=self.server_name, + firewall_rule_name=self.name) + self.log("Response : {0}".format(response)) + self.log("PostgreSQL flexible firewall rule instance : {0} found".format(response.name)) + except ResourceNotFoundError as e: + self.log('Did not find the PostgreSQL flexible firewall rule instance. Exception as {0}'.format(str(e))) + return None + return self.format_item(response) + + def format_item(self, item): + d = item.as_dict() + d = { + 'resource_group': self.resource_group, + 'id': d['id'], + 'server_name': self.server_name, + 'name': d['name'], + 'start_ip_address': d['start_ip_address'], + 'end_ip_address': d['end_ip_address'] + } + return d + + +def main(): + """Main execution""" + AzureRMPostgreSqlFlexibleFirewallRules() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexiblefirewallrule_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexiblefirewallrule_info.py new file mode 100644 index 000000000..14eb029b4 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexiblefirewallrule_info.py @@ -0,0 +1,187 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_postgresqlflexiblefirewallrule_info +version_added: "2.2.0" +short_description: Get Azure PostgreSQL Flexible Firewall Rule facts +description: + - Get facts of Azure PostgreSQL Flexible Firewall Rule. + +options: + resource_group: + description: + - The name of the resource group. + required: True + type: str + server_name: + description: + - The name of the server. + required: True + type: str + name: + description: + - The name of the server firewall rule. + type: str + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: Get instance of PostgreSQL Flexible Firewall Rule + azure_rm_postgresqlflexiblefirewallrule_info: + resource_group: myResourceGroup + server_name: server_name + name: firewall_rule_name + +- name: List instances of PostgreSQL Flexible Firewall Rule + azure_rm_postgresqlflexiblefirewallrule_info: + resource_group: myResourceGroup + server_name: server_name +''' + +RETURN = ''' +rules: + description: + - A list of dictionaries containing facts for PostgreSQL Flexible Firewall Rule. + returned: always + type: complex + contains: + id: + description: + - Resource ID. + returned: always + type: str + sample: "/subscriptions/xxx-xxx/resourceGroups/testRG/providers/Microsoft.DBforPostgreSQL/flexibleServers/flexibled9b/firewallRules/firewalld9b" + server_name: + description: + - The name of the server. + returned: always + type: str + sample: testserver + name: + description: + - Resource name. + returned: always + type: str + sample: rule1 + start_ip_address: + description: + - The start IP address of the PostgreSQL firewall rule. + returned: always + type: str + sample: 10.0.0.16 + end_ip_address: + description: + - The end IP address of the PostgreSQL firewall rule. + returned: always + type: str + sample: 10.0.0.18 +''' + +try: + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + from azure.core.exceptions import ResourceNotFoundError +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMPostgreSQLFlexibleFirewallRulesInfo(AzureRMModuleBase): + def __init__(self): + # define user inputs into argument + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + server_name=dict( + type='str', + required=True + ), + name=dict( + type='str' + ) + ) + # store the results of the module operation + self.results = dict( + changed=False + ) + self.resource_group = None + self.server_name = None + self.name = None + super(AzureRMPostgreSQLFlexibleFirewallRulesInfo, self).__init__(self.module_arg_spec, supports_check_mode=True, supports_tags=False) + + def exec_module(self, **kwargs): + for key in self.module_arg_spec: + setattr(self, key, kwargs[key]) + + if self.name is not None: + self.results['firewall_rules'] = self.get() + else: + self.results['firewall_rules'] = self.list_by_server() + return self.results + + def get(self): + response = None + try: + response = self.postgresql_flexible_client.firewall_rules.get(resource_group_name=self.resource_group, + server_name=self.server_name, + firewall_rule_name=self.name) + self.log("Response : {0}".format(response)) + except ResourceNotFoundError as e: + self.log('Could not get facts for FirewallRules. Exception as {0}'.format(str(e))) + return [] + + return [self.format_item(response)] + + def list_by_server(self): + response = None + results = [] + try: + response = self.postgresql_flexible_client.firewall_rules.list_by_server(resource_group_name=self.resource_group, + server_name=self.server_name) + self.log("Response : {0}".format(response)) + except Exception as e: + self.log('Could not get facts for FirewallRules. Exception as {0}'.format(str(e))) + return [] + + if response is not None: + for item in response: + results.append(self.format_item(item)) + + return results + + def format_item(self, item): + d = item.as_dict() + d = { + 'resource_group': self.resource_group, + 'id': d['id'], + 'server_name': self.server_name, + 'name': d['name'], + 'start_ip_address': d['start_ip_address'], + 'end_ip_address': d['end_ip_address'] + } + return d + + +def main(): + AzureRMPostgreSQLFlexibleFirewallRulesInfo() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibleserver.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibleserver.py new file mode 100644 index 000000000..335dc53c8 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibleserver.py @@ -0,0 +1,928 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_postgresqlflexibleserver +version_added: "2.2.0" +short_description: Manage PostgreSQL Flexible Server instance +description: + - Create, update and delete instance of PostgreSQL Flexible Server. + +options: + resource_group: + description: + - The name of the resource group that contains the resource. + - You can obtain this value from the Azure Resource Manager API or the portal. + required: True + type: str + name: + description: + - The name of the flexible server. + required: True + type: str + sku: + description: + - The SKU (pricing tier) of the server. + type: dict + suboptions: + name: + description: + - The name of the sku, typically, tier + family + cores, such as Standard_D4s_v3. + type: str + required: True + tier: + description: + - The tier of the particular + type: str + choices: + - Burstable + - GeneralPurpose + - MemoryOptimized + required: True + location: + description: + - Resource location. If not set, location from the resource group will be used as default. + type: str + storage: + description: + - Storage properties of a server. + type: dict + suboptions: + storage_size_gb: + description: + - The storage size for the server. + type: int + administrator_login: + description: + - The administrator's login name of a server. + - Can only be specified when the server is being created (and is required for creation). + type: str + administrator_login_password: + description: + - The administrator login password (required for server creation). + type: str + version: + description: + - PostgreSQL Server version. + type: str + choices: + - '11' + - '12' + - '13' + fully_qualified_domain_name: + description: + - The fully qualified domain name of a server. + type: str + backup: + description: + - Backup properties of a server. + type: dict + suboptions: + backup_retention_days: + description: + - Backup retention days for the server. + type: int + geo_redundant_backup: + description: + - A value indicating whether Geo-Redundant backup is enabled on the server. + type: str + choices: + - Enabled + - Disabled + network: + description: + - Network properties of a server. + type: dict + suboptions: + delegated_subnet_resource_id: + description: + - Delegated subnet arm resource id. + type: str + private_dns_zone_arm_resource_id: + description: + - Private dns zone arm resource id. + type: str + public_network_access: + description: + - Public network access is enabled or not. + type: str + choices: + - Enabled + - Disabled + high_availability: + description: + - High availability properties of a server. + type: dict + suboptions: + mode: + description: + - The HA mode for the server. + type: str + choices: + - Disabled + - ZoneRedundant + standby_availability_zone: + description: + - Availability zone information of the standby. + type: str + maintenance_window: + description: + - Maintenance window properties of a server. + type: dict + suboptions: + custom_window: + description: + - Indicates whether custom window is enabled or disabled. + type: str + start_hour: + description: + - Start hour for maintenance window. + type: int + start_minute: + description: + - Start minute for maintenance window. + type: int + day_of_week: + description: + - Day of week for maintenance window. + type: int + point_in_time_utc: + description: + - Restore point creation time (ISO8601 format), specifying the time to restore from. + - It's required when I(create_mode=PointInTimeRestore). + type: str + availability_zone: + description: + - Availability zone information of the server + type: str + create_mode: + description: + - The mode to create a new PostgreSQL server. + type: str + choices: + - Default + - Create + - Update + - PointInTimeRestore + source_server_resource_id: + description: + - The source server resource ID to restore from. + - It's required when I(create_mode=PointInTimeRestore) + type: str + state: + description: + - Assert the state of the PostgreSQL Flexible server. + - Use C(present) to create or update a server and C(absent) to delete it. + default: present + type: str + choices: + - present + - absent + is_restart: + description: + - Whether to restart the Post gresql server. + type: bool + default: False + is_stop: + description: + - Whether to stop the Post gresql server. + type: bool + default: False + is_start: + description: + - Whether to start the Post gresql server. + type: bool + default: False + +extends_documentation_fragment: + - azure.azcollection.azure + - azure.azcollection.azure_tags + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: Create (or update) PostgreSQL Flexible Server + azure_rm_postgresqlflexibleserver: + resource_group: myResourceGroup + name: testserver + sku: + name: Standard_B1ms + tier: Burstable + administrator_login: azureuser + administrator_login_password: Fred@0329 + version: 12 + storage: + storage_size_gb: 128 + fully_qualified_domain_name: st-private-dns-zone.postgres.database.azure.com + backup: + backup_retention_days: 7 + geo_redundant_backup: Disabled + maintenance_window: + custom_window: Enabled + start_hour: 8 + start_minute: 0 + day_of_week: 0 + point_in_time_utc: 2023-05-31T00:28:17.7279547+00:00 + availability_zone: 1 + create_mode: Default + +- name: Delete PostgreSQL Flexible Server + azure_rm_postgresqlflexibleserver: + resource_group: myResourceGroup + name: testserver + state: absent +''' + +RETURN = ''' +servers: + description: + - A list of dictionaries containing facts for PostgreSQL Flexible servers. + returned: always + type: complex + contains: + id: + description: + - Resource ID of the postgresql flexible server. + returned: always + type: str + sample: "/subscriptions/xxx/resourceGroups/myResourceGroup/providers/Microsoft.DBforPostgreSQL/flexibleservers/postgresql3" + resource_group: + description: + - Resource group name. + returned: always + type: str + sample: myResourceGroup + name: + description: + - Resource name. + returned: always + type: str + sample: postgreabdud1223 + location: + description: + - The location the resource resides in. + returned: always + type: str + sample: eastus + sku: + description: + - The SKU of the server. + returned: always + type: complex + contains: + name: + description: + - The name of the SKU. + returned: always + type: str + sample: Standard_B1ms + tier: + description: + - The tier of the particular SKU. + returned: always + type: str + sample: Burstable + storage: + description: + - The maximum storage allowed for a server. + returned: always + type: complex + contains: + storage_size_gb: + description: + - ax storage allowed for a server. + type: int + returned: always + sample: 128 + administrator_login: + description: + - The administrator's login name of a server. + returned: always + type: str + sample: azureuser + version: + description: + - Flexible Server version. + returned: always + type: str + sample: "12" + choices: + - '11' + - '12' + - '13' + fully_qualified_domain_name: + description: + - The fully qualified domain name of the flexible server. + returned: always + type: str + sample: postflexiblefredpgsqlflexible.postgres.database.azure.com + availability_zone: + description: + - Availability zone information of the server. + type: str + returned: always + sample: 1 + backup: + description: + - Backup properties of a server. + type: complex + returned: always + contains: + backup_retention_days: + description: + - Backup retention days for the server. + type: int + returned: always + sample: 7 + geo_redundant_backup: + description: + - A value indicating whether Geo-Redundant backup is enabled on the server. + type: str + returned: always + sample: Disabled + high_availability: + description: + - High availability properties of a server. + type: complex + returned: always + contains: + mode: + description: + - The HA mode for the server. + returned: always + sample: Disabled + type: str + standby_availability_zone: + description: + - availability zone information of the standby. + type: str + returned: always + sample: null + maintenance_window: + description: + - Maintenance window properties of a server. + type: complex + returned: always + contains: + custom_window: + description: + - Indicates whether custom window is enabled or disabled. + returned: always + sample: Enabled + type: str + day_of_week: + description: + - Day of week for maintenance window. + returned: always + sample: 0 + type: int + start_hour: + description: + - Start hour for maintenance window. + type: int + returned: always + sample: 8 + start_minute: + description: + - Start minute for maintenance window. + type: int + returned: always + sample: 0 + network: + description: + - Network properties of a server. + type: complex + returned: always + contains: + delegated_subnet_resource_id: + description: + - Delegated subnet arm resource id. + type: str + returned: always + sample: null + private_dns_zone_arm_resource_id: + description: + - Private dns zone arm resource id. + type: str + returned: always + sample: null + public_network_access: + description: + - Public network access is enabled or not. + type: str + returned: always + sample: Enabled + point_in_time_utc: + description: + - Restore point creation time (ISO8601 format). + type: str + sample: null + returned: always + source_server_resource_id: + description: + - The source server resource ID to restore from. + type: str + returned: always + sample: null + system_data: + description: + - The system metadata relating to this resource. + type: complex + returned: always + contains: + created_by: + description: + - The identity that created the resource. + type: str + returned: always + sample: null + created_by_type: + description: + - The type of identity that created the resource. + returned: always + type: str + sample: null + created_at: + description: + - The timestamp of resource creation (UTC). + returned: always + sample: null + type: str + last_modified_by: + description: + - The identity that last modified the resource. + type: str + returned: always + sample: null + last_modified_by_type: + description: + - The type of identity that last modified the resource. + returned: always + sample: null + type: str + last_modified_at: + description: + - The timestamp of resource last modification (UTC). + returned: always + sample: null + type: str + tags: + description: + - Tags assigned to the resource. Dictionary of string:string pairs. + type: dict + returned: always + sample: { tag1: abc } +''' + + +try: + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + from azure.core.exceptions import ResourceNotFoundError + from azure.core.polling import LROPoller +except ImportError: + # This is handled in azure_rm_common + pass + + +sku_spec = dict( + name=dict(type='str', required=True), + tier=dict(type='str', required=True, choices=["Burstable", "GeneralPurpose", "MemoryOptimized"]) +) + + +maintenance_window_spec = dict( + custom_window=dict(type='str'), + start_hour=dict(type='int'), + start_minute=dict(type='int'), + day_of_week=dict(type='int'), +) + + +high_availability_spec = dict( + mode=dict(type='str', choices=["Disabled", "ZoneRedundant"]), + standby_availability_zone=dict(type='str') +) + + +network_spec = dict( + delegated_subnet_resource_id=dict(type='str'), + private_dns_zone_arm_resource_id=dict(type='str'), + public_network_access=dict(type='str', choices=["Enabled", "Disabled"]) +) + + +backup_spec = dict( + backup_retention_days=dict(type='int'), + geo_redundant_backup=dict(type='str', choices=["Enabled", "Disabled"]), +) + + +storage_spec = dict( + storage_size_gb=dict(type='int') +) + + +class AzureRMPostgreSqlFlexibleServers(AzureRMModuleBase): + """Configuration class for an Azure RM PostgreSQL Flexible Server resource""" + + def __init__(self): + self.module_arg_spec = dict( + resource_group=dict( + type='str', + required=True + ), + name=dict( + type='str', + required=True + ), + sku=dict( + type='dict', + options=sku_spec + ), + location=dict( + type='str' + ), + administrator_login=dict( + type='str' + ), + administrator_login_password=dict( + type='str', + no_log=True + ), + version=dict( + type='str', + choices=['11', '12', '13'] + ), + fully_qualified_domain_name=dict( + type='str', + ), + storage=dict( + type='dict', + options=storage_spec + ), + backup=dict( + type='dict', + options=backup_spec + ), + network=dict( + type='dict', + options=network_spec + ), + high_availability=dict( + type='dict', + options=high_availability_spec + ), + maintenance_window=dict( + type='dict', + options=maintenance_window_spec + ), + point_in_time_utc=dict( + type='str' + ), + availability_zone=dict( + type='str' + ), + create_mode=dict( + type='str', + choices=['Default', 'Create', 'Update', 'PointInTimeRestore'] + ), + is_start=dict( + type='bool', + default=False, + ), + is_restart=dict( + type='bool', + default=False + ), + is_stop=dict( + type='bool', + default=False + ), + source_server_resource_id=dict( + type='str' + ), + state=dict( + type='str', + default='present', + choices=['present', 'absent'] + ) + ) + + self.resource_group = None + self.name = None + self.parameters = dict() + self.update_parameters = dict() + self.tags = None + self.is_start = None + self.is_stop = None + self.is_restart = None + + self.results = dict(changed=False) + self.state = None + + super(AzureRMPostgreSqlFlexibleServers, self).__init__(derived_arg_spec=self.module_arg_spec, + supports_check_mode=True, + supports_tags=True) + + def exec_module(self, **kwargs): + """Main module execution method""" + + for key in list(self.module_arg_spec.keys()) + ['tags']: + if hasattr(self, key): + setattr(self, key, kwargs[key]) + elif kwargs[key] is not None: + self.parameters[key] = kwargs[key] + for key in ['location', 'sku', 'administrator_login_password', 'storage', 'backup', 'high_availability', 'maintenance_window', 'create_mode']: + self.update_parameters[key] = kwargs[key] + + old_response = None + response = None + changed = False + + resource_group = self.get_resource_group(self.resource_group) + + if "location" not in self.parameters: + self.parameters["location"] = resource_group.location + self.update_parameters["location"] = resource_group.location + + old_response = self.get_postgresqlflexibleserver() + + if not old_response: + self.log("PostgreSQL Flexible Server instance doesn't exist") + if self.state == 'present': + if not self.check_mode: + response = self.create_postgresqlflexibleserver(self.parameters) + if self.is_stop: + self.stop_postgresqlflexibleserver() + elif self.is_start: + self.start_postgresqlflexibleserver() + elif self.is_restart: + self.restart_postgresqlflexibleserver() + changed = True + else: + self.log("PostgreSQL Flexible Server instance doesn't exist, Don't need to delete") + else: + self.log("PostgreSQL Flexible Server instance already exists") + if self.state == 'present': + update_flag = False + if self.update_parameters.get('sku') is not None: + for key in self.update_parameters['sku'].keys(): + if self.update_parameters['sku'][key] is not None and self.update_parameters['sku'][key] != old_response['sku'].get(key): + update_flag = True + else: + self.update_parameters['sku'][key] = old_response['sku'].get(key) + + if self.update_parameters.get('storage') is not None and self.update_parameters['storage'] != old_response['storage']: + update_flag = True + else: + self.update_parameters['storage'] = old_response['storage'] + + if self.update_parameters.get('backup') is not None: + for key in self.update_parameters['backup'].keys(): + if self.update_parameters['backup'][key] is not None and self.update_parameters['backup'][key] != old_response['backup'].get(key): + update_flag = True + else: + self.update_parameters['backup'][key] = old_response['backup'].get(key) + + if self.update_parameters.get('high_availability') is not None: + for key in self.update_parameters['high_availability'].keys(): + if (self.update_parameters['high_availability'][key] is not None) and\ + (self.update_parameters['high_availability'][key] != old_response['high_availability'].get(key)): + update_flag = True + else: + self.update_parameters['high_availability'][key] = old_response['high_availability'].get(key) + + if self.update_parameters.get('maintenance_window') is not None: + for key in self.update_parameters['maintenance_window'].keys(): + if (self.update_parameters['maintenance_window'][key] is not None) and\ + (self.update_parameters['maintenance_window'][key] != old_response['maintenance_window'].get(key)): + update_flag = True + else: + self.update_parameters['maintenance_window'][key] = old_response['maintenance_window'].get(key) + + update_tags, new_tags = self.update_tags(old_response['tags']) + self.update_parameters['tags'] = new_tags + if update_tags: + update_flag = True + + if update_flag: + changed = True + if not self.check_mode: + response = self.update_postgresqlflexibleserver(self.update_parameters) + else: + response = old_response + if self.is_stop: + self.stop_postgresqlflexibleserver() + changed = True + elif self.is_start: + self.start_postgresqlflexibleserver() + changed = True + elif self.is_restart: + self.restart_postgresqlflexibleserver() + changed = True + else: + if not self.check_mode: + if self.is_stop: + self.stop_postgresqlflexibleserver() + changed = True + elif self.is_start: + self.start_postgresqlflexibleserver() + changed = True + elif self.is_restart: + self.restart_postgresqlflexibleserver() + changed = True + response = old_response + else: + self.log("PostgreSQL Flexible Server instance already exist, will be deleted") + changed = True + if not self.check_mode: + response = self.delete_postgresqlflexibleserver() + + self.results['changed'] = changed + self.results['state'] = response + + return self.results + + def update_postgresqlflexibleserver(self, body): + ''' + Updates PostgreSQL Flexible Server with the specified configuration. + :return: deserialized PostgreSQL Flexible Server instance state dictionary + ''' + self.log("Updating the PostgreSQL Flexible Server instance {0}".format(self.name)) + try: + # structure of parameters for update must be changed + response = self.postgresql_flexible_client.servers.begin_update(resource_group_name=self.resource_group, + server_name=self.name, + parameters=body) + if isinstance(response, LROPoller): + response = self.get_poller_result(response) + + except Exception as exc: + self.log('Error attempting to create the PostgreSQL Flexible Server instance.') + self.fail("Error updating the PostgreSQL Flexible Server instance: {0}".format(str(exc))) + return self.format_item(response) + + def create_postgresqlflexibleserver(self, body): + ''' + Creates PostgreSQL Flexible Server with the specified configuration. + :return: deserialized PostgreSQL Flexible Server instance state dictionary + ''' + self.log("Creating the PostgreSQL Flexible Server instance {0}".format(self.name)) + try: + response = self.postgresql_flexible_client.servers.begin_create(resource_group_name=self.resource_group, + server_name=self.name, + parameters=body) + if isinstance(response, LROPoller): + response = self.get_poller_result(response) + + except Exception as exc: + self.log('Error attempting to create the PostgreSQL Flexible Server instance.') + self.fail("Error creating the PostgreSQL Flexible Server instance: {0}".format(str(exc))) + return self.format_item(response) + + def delete_postgresqlflexibleserver(self): + ''' + Deletes specified PostgreSQL Flexible Server instance in the specified subscription and resource group. + + :return: True + ''' + self.log("Deleting the PostgreSQL Flexible Server instance {0}".format(self.name)) + try: + self.postgresql_flexible_client.servers.begin_delete(resource_group_name=self.resource_group, + server_name=self.name) + except Exception as e: + self.log('Error attempting to delete the PostgreSQL Flexible Server instance.') + self.fail("Error deleting the PostgreSQL Flexible Server instance: {0}".format(str(e))) + + def stop_postgresqlflexibleserver(self): + ''' + Stop PostgreSQL Flexible Server instance in the specified subscription and resource group. + + :return: True + ''' + self.log("Stop the PostgreSQL Flexible Server instance {0}".format(self.name)) + try: + self.postgresql_flexible_client.servers.begin_stop(resource_group_name=self.resource_group, + server_name=self.name) + except Exception as e: + self.log('Error attempting to stop the PostgreSQL Flexible Server instance.') + self.fail("Error stop the PostgreSQL Flexible Server instance: {0}".format(str(e))) + + def start_postgresqlflexibleserver(self): + ''' + Start PostgreSQL Flexible Server instance in the specified subscription and resource group. + + :return: True + ''' + self.log("Starting the PostgreSQL Flexible Server instance {0}".format(self.name)) + try: + self.postgresql_flexible_client.servers.begin_start(resource_group_name=self.resource_group, + server_name=self.name) + except Exception as e: + self.log('Error attempting to start the PostgreSQL Flexible Server instance.') + self.fail("Error starting the PostgreSQL Flexible Server instance: {0}".format(str(e))) + + def restart_postgresqlflexibleserver(self): + ''' + Restart PostgreSQL Flexible Server instance in the specified subscription and resource group. + + :return: True + ''' + self.log("Restarting the PostgreSQL Flexible Server instance {0}".format(self.name)) + try: + self.postgresql_flexible_client.servers.begin_restart(resource_group_name=self.resource_group, + server_name=self.name) + except Exception as e: + self.log('Error attempting to restart the PostgreSQL Flexible Server instance.') + self.fail("Error restarting the PostgreSQL Flexible Server instance: {0}".format(str(e))) + + def get_postgresqlflexibleserver(self): + ''' + Gets the properties of the specified PostgreSQL Flexible Server. + + :return: deserialized PostgreSQL Flexible Server instance state dictionary + ''' + self.log("Checking if the PostgreSQL Flexible Server instance {0} is present".format(self.name)) + try: + response = self.postgresql_flexible_client.servers.get(resource_group_name=self.resource_group, + server_name=self.name) + self.log("Response : {0}".format(response)) + self.log("PostgreSQL Flexible Server instance : {0} found".format(response.name)) + except ResourceNotFoundError as e: + self.log('Did not find the PostgreSQL Flexible Server instance. Exception as {0}'.format(str(e))) + return None + + return self.format_item(response) + + def format_item(self, item): + result = dict( + id=item.id, + resource_group=self.resource_group, + name=item.name, + sku=dict(), + location=item.location, + tags=item.tags, + system_data=dict(), + administrator_login=item.administrator_login, + version=item.version, + minor_version=item.minor_version, + fully_qualified_domain_name=item.fully_qualified_domain_name, + storage=dict(), + backup=dict(), + network=dict(), + high_availability=dict(), + maintenance_window=dict(), + source_server_resource_id=item.source_server_resource_id, + point_in_time_utc=item.point_in_time_utc, + availability_zone=item.availability_zone, + ) + if item.sku is not None: + result['sku']['name'] = item.sku.name + result['sku']['tier'] = item.sku.tier + if item.system_data is not None: + result['system_data']['created_by'] = item.system_data.created_by + result['system_data']['created_by_type'] = item.system_data.created_by_type + result['system_data']['created_at'] = item.system_data.created_at + result['system_data']['last_modified_by'] = item.system_data.last_modified_by + result['system_data']['last_modified_by_type'] = item.system_data.last_modified_by_type + result['system_data']['last_modified_at'] = item.system_data.last_modified_at + if item.storage is not None: + result['storage']['storage_size_gb'] = item.storage.storage_size_gb + if item.backup is not None: + result['backup']['backup_retention_days'] = item.backup.backup_retention_days + result['backup']['geo_redundant_backup'] = item.backup.geo_redundant_backup + if item.network is not None: + result['network']['public_network_access'] = item.network.public_network_access + result['network']['delegated_subnet_resource_id'] = item.network.delegated_subnet_resource_id + result['network']['private_dns_zone_arm_resource_id'] = item.network.private_dns_zone_arm_resource_id + if item.high_availability is not None: + result['high_availability']['mode'] = item.high_availability.mode + result['high_availability']['standby_availability_zone'] = item.high_availability.standby_availability_zone + if item.maintenance_window is not None: + result['maintenance_window']['custom_window'] = item.maintenance_window.custom_window + result['maintenance_window']['start_minute'] = item.maintenance_window.start_minute + result['maintenance_window']['start_hour'] = item.maintenance_window.start_hour + result['maintenance_window']['day_of_week'] = item.maintenance_window.day_of_week + + return result + + +def main(): + """Main execution""" + AzureRMPostgreSqlFlexibleServers() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibleserver_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibleserver_info.py new file mode 100644 index 000000000..50fe9adc5 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_postgresqlflexibleserver_info.py @@ -0,0 +1,443 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_postgresqlflexibleserver_info +version_added: "2.2.0" +short_description: Get Azure PostgreSQL Flexible Server facts +description: + - Get facts of PostgreSQL Flexible Server. + +options: + resource_group: + description: + - The name of the resource group that contains the resource. You can obtain this value from the Azure Resource Manager API or the portal. + type: str + name: + description: + - The name of the server. + type: str + tags: + description: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + type: list + elements: str + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: Get instance of PostgreSQL Flexible Server + azure_rm_postgresqlflexibleserver_info: + resource_group: myResourceGroup + name: server_name + +- name: List instances of PostgreSQL Flexible Server + azure_rm_postgresqlflexibleserver_info: + resource_group: myResourceGroup + tags: + - key +''' + +RETURN = ''' +servers: + description: + - A list of dictionaries containing facts for PostgreSQL Flexible servers. + returned: always + type: complex + contains: + id: + description: + - Resource ID of the postgresql flexible server. + returned: always + type: str + sample: "/subscriptions/xxx/resourceGroups/myResourceGroup/providers/Microsoft.DBforPostgreSQL/flexibleservers/postgresql3" + resource_group: + description: + - Resource group name. + returned: always + type: str + sample: myResourceGroup + name: + description: + - Resource name. + returned: always + type: str + sample: postgreabdud1223 + location: + description: + - The location the resource resides in. + returned: always + type: str + sample: eastus + sku: + description: + - The SKU of the server. + returned: always + type: complex + contains: + name: + description: + - The name of the SKU. + returned: always + type: str + sample: Standard_B1ms + tier: + description: + - The tier of the particular SKU. + returned: always + type: str + sample: Burstable + storage: + description: + - The maximum storage allowed for a server. + returned: always + type: complex + contains: + storage_size_gb: + description: + - Max storage allowed for a server. + type: int + returned: always + sample: 128 + administrator_login: + description: + - The administrator's login name of a server. + returned: always + type: str + sample: azureuser + version: + description: + - Flexible Server version. + returned: always + type: str + sample: "12" + fully_qualified_domain_name: + description: + - The fully qualified domain name of the flexible server. + returned: always + type: str + sample: postflexiblefredpgsqlflexible.postgres.database.azure.com + availability_zone: + description: + - availability zone information of the server. + type: str + returned: always + sample: 1 + backup: + description: + - Backup properties of a server. + type: complex + returned: always + contains: + backup_retention_days: + description: + - Backup retention days for the server. + type: int + returned: always + sample: 7 + geo_redundant_backup: + description: + - A value indicating whether Geo-Redundant backup is enabled on the server. + type: str + returned: always + sample: Disabled + high_availability: + description: + - High availability properties of a server. + type: complex + returned: always + contains: + mode: + description: + - The HA mode for the server. + returned: always + sample: Disabled + type: str + standby_availability_zone: + description: + - availability zone information of the standby. + type: str + returned: always + sample: null + maintenance_window: + description: + - Maintenance window properties of a server. + type: complex + returned: always + contains: + custom_window: + description: + - Indicates whether custom window is enabled or disabled. + returned: always + sample: Enabled + type: str + day_of_week: + description: + - Day of week for maintenance window. + returned: always + sample: 0 + type: int + start_hour: + description: + - Start hour for maintenance window. + type: int + returned: always + sample: 8 + start_minute: + description: + - Start minute for maintenance window. + type: int + returned: always + sample: 0 + network: + description: + - Network properties of a server. + type: complex + returned: always + contains: + delegated_subnet_resource_id: + description: + - Delegated subnet arm resource id. + type: str + returned: always + sample: null + private_dns_zone_arm_resource_id: + description: + - Private dns zone arm resource id. + type: str + returned: always + sample: null + public_network_access: + description: + - Public network access is enabled or not. + type: str + returned: always + sample: Enabled + point_in_time_utc: + description: + - Restore point creation time (ISO8601 format). + type: str + sample: null + returned: always + source_server_resource_id: + description: + - The source server resource ID to restore from. + type: str + returned: always + sample: null + system_data: + description: + - The system metadata relating to this resource. + type: complex + returned: always + contains: + created_by: + description: + - The identity that created the resource. + type: str + returned: always + sample: null + created_by_type: + description: + - The type of identity that created the resource. + returned: always + type: str + sample: null + created_at: + description: + - The timestamp of resource creation (UTC). + returned: always + sample: null + type: str + last_modified_by: + description: + - The identity that last modified the resource. + type: str + returned: always + sample: null + last_modified_by_type: + description: + - The type of identity that last modified the resource. + returned: always + sample: null + type: str + last_modified_at: + description: + - The timestamp of resource last modification (UTC). + returned: always + sample: null + type: str + tags: + description: + - Tags assigned to the resource. Dictionary of string:string pairs. + type: dict + returned: always + sample: { tag1: abc } +''' + + +try: + from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + from azure.core.exceptions import ResourceNotFoundError +except ImportError: + # This is handled in azure_rm_common + pass + + +class AzureRMPostgreSqlFlexibleServersInfo(AzureRMModuleBase): + def __init__(self): + # define user inputs into argument + self.module_arg_spec = dict( + resource_group=dict( + type='str', + ), + name=dict( + type='str' + ), + tags=dict( + type='list', + elements='str' + ) + ) + # store the results of the module operation + self.results = dict( + changed=False + ) + self.resource_group = None + self.name = None + self.tags = None + super(AzureRMPostgreSqlFlexibleServersInfo, self).__init__(self.module_arg_spec, supports_check_mode=True, supports_tags=False, facts_module=True) + + def exec_module(self, **kwargs): + for key in self.module_arg_spec: + setattr(self, key, kwargs[key]) + + if self.resource_group is not None and self.name is not None: + self.results['servers'] = self.get() + elif self.resource_group is not None: + self.results['servers'] = self.list_by_resource_group() + else: + self.results['servers'] = self.list_all() + return self.results + + def get(self): + response = None + results = [] + try: + response = self.postgresql_flexible_client.servers.get(resource_group_name=self.resource_group, + server_name=self.name) + self.log("Response : {0}".format(response)) + except ResourceNotFoundError: + self.log('Could not get facts for PostgreSQL Flexible Server.') + + if response and self.has_tags(response.tags, self.tags): + results.append(self.format_item(response)) + + return results + + def list_by_resource_group(self): + response = None + results = [] + try: + response = self.postgresql_flexible_client.servers.list_by_resource_group(resource_group_name=self.resource_group) + self.log("Response : {0}".format(response)) + except Exception: + self.log('Could not get facts for PostgreSQL Flexible Servers.') + + if response is not None: + for item in response: + if self.has_tags(item.tags, self.tags): + results.append(self.format_item(item)) + + return results + + def list_all(self): + response = None + results = [] + try: + response = self.postgresql_flexible_client.servers.list() + self.log("Response : {0}".format(response)) + except Exception: + self.log('Could not get facts for PostgreSQL Flexible Servers.') + + if response is not None: + for item in response: + if self.has_tags(item.tags, self.tags): + results.append(self.format_item(item)) + + return results + + def format_item(self, item): + result = dict( + id=item.id, + resource_group=self.resource_group, + name=item.name, + sku=dict(), + location=item.location, + tags=item.tags, + system_data=dict(), + administrator_login=item.administrator_login, + version=item.version, + minor_version=item.minor_version, + fully_qualified_domain_name=item.fully_qualified_domain_name, + storage=dict(), + backup=dict(), + network=dict(), + high_availability=dict(), + maintenance_window=dict(), + source_server_resource_id=item.source_server_resource_id, + point_in_time_utc=item.point_in_time_utc, + availability_zone=item.availability_zone, + ) + if item.sku is not None: + result['sku']['name'] = item.sku.name + result['sku']['tier'] = item.sku.tier + if item.system_data is not None: + result['system_data']['created_by'] = item.system_data.created_by + result['system_data']['created_by_type'] = item.system_data.created_by_type + result['system_data']['created_at'] = item.system_data.created_at + result['system_data']['last_modified_by'] = item.system_data.last_modified_by + result['system_data']['last_modified_by_type'] = item.system_data.last_modified_by_type + result['system_data']['last_modified_at'] = item.system_data.last_modified_at + if item.storage is not None: + result['storage']['storage_size_gb'] = item.storage.storage_size_gb + if item.backup is not None: + result['backup']['backup_retention_days'] = item.backup.backup_retention_days + result['backup']['geo_redundant_backup'] = item.backup.geo_redundant_backup + if item.network is not None: + result['network']['public_network_access'] = item.network.public_network_access + result['network']['delegated_subnet_resource_id'] = item.network.delegated_subnet_resource_id + result['network']['private_dns_zone_arm_resource_id'] = item.network.private_dns_zone_arm_resource_id + if item.high_availability is not None: + result['high_availability']['mode'] = item.high_availability.mode + result['high_availability']['standby_availability_zone'] = item.high_availability.standby_availability_zone + if item.maintenance_window is not None: + result['maintenance_window']['custom_window'] = item.maintenance_window.custom_window + result['maintenance_window']['start_minute'] = item.maintenance_window.start_minute + result['maintenance_window']['start_hour'] = item.maintenance_window.start_hour + result['maintenance_window']['day_of_week'] = item.maintenance_window.day_of_week + + return result + + +def main(): + AzureRMPostgreSqlFlexibleServersInfo() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednsrecordset.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednsrecordset.py index 3560139e7..f2e9e92f7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednsrecordset.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_privatednsrecordset.py @@ -324,8 +324,10 @@ class AzureRMPrivateDNSRecordSet(AzureRMModuleBase): resource_group=dict(type='str', required=True), relative_name=dict(type='str', required=True), zone_name=dict(type='str', required=True), - record_type=dict(choices=RECORD_ARGSPECS.keys(), required=True, type='str'), - record_mode=dict(choices=['append', 'purge'], default='purge'), + record_type=dict(choices=['A', 'AAAA', 'CNAME', 'MX', 'PTR', 'SRV', 'TXT', 'SOA'], + required=True, + type='str'), + record_mode=dict(type='str', choices=['append', 'purge'], default='purge'), state=dict(choices=['present', 'absent'], default='present', type='str'), time_to_live=dict(type='int', default=3600), records=dict(type='list', elements='dict') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipprefix.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipprefix.py new file mode 100644 index 000000000..90bfafc41 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipprefix.py @@ -0,0 +1,455 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-Sun (@Fred-Sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_publicipprefix + +version_added: "2.2.0" + +short_description: Manage Azure Public IP prefix + +description: + - Create, update and delete a Public IP prefix. + +options: + resource_group: + description: + - Name of resource group with which the Public IP prefix is associated. + required: true + type: str + name: + description: + - Name of the Public IP prefix. + required: true + type: str + state: + description: + - Assert the state of the Public IP. Use C(present) to create or update a and C(absent) to delete. + default: present + type: str + choices: + - absent + - present + location: + description: + - Valid Azure location. Defaults to location of the resource group. + type: str + sku: + description: + - The public IP prefix SKU. + type: dict + suboptions: + name: + description: + - Name of a public IP prefix SKU. + type: str + choices: + - Standard + tier: + description: + - Tier of a public IP prefix SKU. + type: str + choices: + - Regional + - Global + custom_ip_prefix: + description: + - The Custom IP prefix that this prefix is associated with. + type: dict + suboptions: + id: + description: + - Resource ID. + type: str + extended_location: + description: + - The extended location of the public ip address. + type: str + ip_tags: + description: + - The list of tags associated with the public IP prefix. + type: list + elements: dict + suboptions: + ip_tag_type: + description: + - The IP tag type. Example as FirstPartyUsage. + type: str + tag: + description: + - The value of the IP tag associated with the public IP. Example as SQL. + type: str + public_ip_address_version: + description: + - The public IP address version. + type: str + choices: + - IPV4 + - IPV6 + zones: + description: + - A list of availability zones denoting the IP prefix allocated for the resource needs to come from. + type: list + elements: str + choices: + - '1' + - '2' + - '3' + prefix_length: + description: + - The Length of the Public IP Prefix. + type: int + +extends_documentation_fragment: + - azure.azcollection.azure + - azure.azcollection.azure_tags + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) +''' + +EXAMPLES = ''' +- name: Create a public ip prefix + azure_rm_publicipprefix: + resource_group: myResourceGroup + name: my_public_ip + public_ip_address_version: IPV4 + prefix_length: 29 + sku: + name: Standard + tier: Regional + zones: + - 1 + tags: + key1: value1 + +- name: Delete public ip prefix + azure_rm_publicipprefix: + resource_group: myResourceGroup + name: my_public_ipprefix + state: absent +''' + +RETURN = ''' +state: + description: + - List of public IP prefixes dicts. + returned: always + type: complex + contains: + id: + description: + - Resource ID. + returned: always + type: str + sample: /subscriptions/xxx---xxxxx/resourceGroups/v-xisuRG/providers/Microsoft.Network/publicIPPrefixes/pipb57dc95224 + name: + description: + - Name of the public IP prefix. + returned: always + type: str + sample: prefix57dc95224 + type: + description: + - Resource type. + returned: always + type: str + sample: "Microsoft.Network/publicIPPrefixes" + location: + description: + - Resource location. + returned: always + type: str + sample: eastus + tags: + description: + - Resource tags. + returned: always + type: dict + sample: { + "delete": "on-exit", + "testing": "testing" + } + public_ip_address_version: + description: + - The public IP address version. + - Possible values are C(IPv4) and C(IPv6). + returned: always + type: str + sample: IPv4 + ip_tags: + description: + - The list of tags associated with the public IP prefixes. + returned: always + type: list + sample: [{'type': 'FirstPartyUsage', 'value': 'Storage'}] + resource_guid: + description: + - The resource GUID property of the public IP prefix resource. + type: str + sample: "47cafa04-851d-4579-894d-74ad6afe3233" + custom_ip_prefix: + description: + - The customIpPrefix that this prefix is associated with. + type: dict + returned: always + sample: {} + public_ip_addresses: + description: + - The list of all referenced PublicIPAddresses. + type: list + sample: [] +''' + +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + +try: + from azure.core.exceptions import ResourceNotFoundError +except ImportError: + # This is handled in azure_rm_common + pass + + +def prefix_to_dict(prefix): + result = dict( + id=prefix.id, + name=prefix.name, + tags=prefix.tags, + type=prefix.type, + location=prefix.location, + public_ip_address_version=prefix.public_ip_address_version, + prefix_length=prefix.prefix_length, + provisioning_state=prefix.provisioning_state, + etag=prefix.etag, + zones=prefix.zones, + sku=dict(), + ip_tags=list(), + custom_ip_prefix=dict(), + ip_prefix=prefix.ip_prefix, + resource_guid=prefix.resource_guid, + public_ip_addresses=list(), + extended_location=prefix.extended_location + ) + if prefix.public_ip_addresses: + result['public_ip_addresses'] = [x.id for x in prefix.public_ip_addresses] + if prefix.sku: + result['sku']['name'] = prefix.sku.name + result['sku']['tier'] = prefix.sku.tier + if prefix.custom_ip_prefix: + result['custom_ip_prefix']['id'] = prefix.custom_ip_prefix.id + if prefix.ip_tags: + result['ip_tags'] = [dict(type=x.ip_tag_type, value=x.tag) for x in prefix.ip_tags] + return result + + +class AzureRMPublicIPPrefix(AzureRMModuleBase): + + def __init__(self): + + self.module_arg_spec = dict( + resource_group=dict(type='str', required=True), + name=dict(type='str', required=True), + state=dict(type='str', default='present', choices=['present', 'absent']), + location=dict(type='str'), + public_ip_address_version=dict(type='str', choices=['IPV4', 'IPV6']), + extended_location=dict(type='str'), + prefix_length=dict(type='int'), + custom_ip_prefix=dict( + type='dict', + options=dict( + id=dict(type='str') + ) + ), + sku=dict( + type='dict', + options=dict( + name=dict(type='str', choices=['Standard']), + tier=dict(type='str', choices=['Regional', 'Global']) + ) + ), + ip_tags=dict( + type='list', + elements='dict', + options=dict( + ip_tag_type=dict(type='str'), + tag=dict(type='str') + ) + ), + zones=dict(type='list', elements='str', choices=['1', '2', '3']) + ) + + self.resource_group = None + self.name = None + self.location = None + self.state = None + self.tags = None + self.zones = None + self.sku = None + self.ip_tags = None + self.public_ip_address_version = None + self.prefix_length = None + self.custom_ip_prefix = None + + self.results = dict( + changed=False, + state=dict() + ) + + super(AzureRMPublicIPPrefix, self).__init__(derived_arg_spec=self.module_arg_spec, + supports_check_mode=True) + + def exec_module(self, **kwargs): + + for key in list(self.module_arg_spec.keys()) + ['tags']: + setattr(self, key, kwargs[key]) + + results = dict() + changed = False + prefix = None + update_tags = False + + resource_group = self.get_resource_group(self.resource_group) + if not self.location: + # Set default location + self.location = resource_group.location + + try: + self.log("Fetch public ip prefix {0}".format(self.name)) + prefix = self.network_client.public_ip_prefixes.get(self.resource_group, self.name) + self.log("Public IP prefix {0} exists".format(self.name)) + + if self.state == 'present': + results = prefix_to_dict(prefix) + + if self.public_ip_address_version is not None and \ + self.public_ip_address_version.lower() != results['public_ip_address_version'].lower(): + changed = False + results['public_ip_address_version'] = self.public_ip_address_version + self.fail("The public_ip_address_version can't be updated") + + if self.prefix_length is not None and self.prefix_length != results['prefix_length']: + changed = False + results['prefix_length'] = self.prefix_length + self.fail("The prefix_length can't be updated") + + if self.sku is not None: + for key in self.sku.keys(): + if self.sku[key] != results['sku'].get(key): + changed = False + self.fail("The sku can't be updated") + results['sku'] = self.sku + + if self.zones is not None and not all(key in results['zones'] for key in self.zones): + changed = False + results['zones'] = self.zones + self.fail("The zone can't be updated") + + if self.extended_location is not None and self.extended_location != results['extended_location']: + changed = False + results['extended_location'] = self.extended_location + self.fail("The extended_location can't be updated") + + if self.ip_tags is not None: + for key in self.ip_tags.keys(): + if self.ip_tags[key] != results['ip_tags'].get(key): + changed = False + results['ip_tags'] = self.ip_tags + self.fail("The ip_tags can't be updated") + + if self.custom_ip_prefix is not None: + if results.get('custom_ip_prefix') is None: + changed = False + results['custom_ip_prefix'] = self.custom_ip_prefix + self.fail("The custom_ip_prefix can't be updated") + elif self.custom_ip_prefix['id'].lower() != results['custom_ip_prefix']['id'].lower(): + changed = False + results['custom_ip_prefix'] = self.custom_ip_prefix + self.fail("The custom_ip_prefix can't be updated") + + update_tags, results['tags'] = self.update_tags(results['tags']) + if update_tags: + self.log("CHANGED: tags") + changed = True + self.tags = results['tags'] + + elif self.state == 'absent': + self.log("CHANGED: public ip prefix {0} exists but requested state is 'absent'".format(self.name)) + changed = True + except ResourceNotFoundError: + self.log('Public ip prefix {0} does not exist'.format(self.name)) + if self.state == 'present': + self.log("CHANGED: public IP prefix {0} does not exist but requested state is 'present'".format(self.name)) + changed = True + + self.results['state'] = results + self.results['changed'] = changed + + if self.check_mode: + results['changed'] = True + return results + + if update_tags: + self.results['state'] = self.update_prefix_tags(self.tags) + + elif changed: + if self.state == 'present': + self.log("Create or Update Public IP prefix {0}".format(self.name)) + prefix = self.network_models.PublicIPPrefix( + location=self.location, + public_ip_address_version=self.public_ip_address_version, + prefix_length=self.prefix_length, + zones=self.zones, + tags=self.tags, + sku=self.sku, + ip_tags=self.ip_tags, + custom_ip_prefix=self.custom_ip_prefix + ) + self.results['state'] = self.create_or_update_prefix(prefix) + + elif self.state == 'absent': + self.log('Delete public ip {0}'.format(self.name)) + self.delete_prefix() + + return self.results + + def update_prefix_tags(self, tags): + try: + prefix = self.network_client.public_ip_prefixes.update_tags(self.resource_group, self.name, dict(tags=tags)) + except Exception as exc: + self.fail("Error updating tags {0} - {1}".format(self.name, str(exc))) + return prefix_to_dict(prefix) + + def create_or_update_prefix(self, prefix): + try: + poller = self.network_client.public_ip_prefixes.begin_create_or_update(self.resource_group, self.name, prefix) + prefix = self.get_poller_result(poller) + except Exception as exc: + self.fail("Error creating or updating {0} - {1}".format(self.name, str(exc))) + return prefix_to_dict(prefix) + + def delete_prefix(self): + try: + poller = self.network_client.public_ip_prefixes.begin_delete(self.resource_group, self.name) + self.get_poller_result(poller) + except Exception as exc: + self.fail("Error deleting {0} - {1}".format(self.name, str(exc))) + + self.results['state']['status'] = 'Deleted' + return True + + +def main(): + AzureRMPublicIPPrefix() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipprefix_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipprefix_info.py new file mode 100644 index 000000000..c8cf0eff1 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_publicipprefix_info.py @@ -0,0 +1,296 @@ +#!/usr/bin/python +# +# Copyright (c) 2024 xuzhang3 (@xuzhang3), Fred-Sun (@Fred-Sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_publicipprefix_info + +version_added: "2.2.0" + +short_description: Get public IP prefix facts + +description: + - Get facts for a specific public IP prefix. + - Get all facts for a specific public IP prefixes within a resource group. + +options: + name: + description: + - The name of the public IP prefix. + type: str + resource_group: + description: + - Limit results by resource group. Required when using name parameter. + type: str + tags: + description: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + type: list + elements: str + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) +''' + +EXAMPLES = ''' +- name: Get facts for one Public IP Prefix + azure_rm_publicipprefix_info: + resource_group: myResourceGroup + name: publicipprefix + +- name: Get facts for all Public IPs within a resource groups + azure_rm_publicipprefix_info: + resource_group: myResourceGroup + tags: + - key:value +''' + +RETURN = ''' +publicipprefix: + description: + - List of public IP prefixes dicts. + returned: always + type: complex + contains: + id: + description: + - Resource ID. + returned: always + type: str + sample: /subscriptions/xxx---xxxxx/resourceGroups/v-xisuRG/providers/Microsoft.Network/publicIPPrefixes/pipb57dc95224 + name: + description: + - Name of the public IP prefix. + returned: always + type: str + sample: prefix57dc95224 + type: + description: + - Resource type. + returned: always + type: str + sample: "Microsoft.Network/publicIPPrefixes" + location: + description: + - Resource location. + returned: always + type: str + sample: eastus + tags: + description: + - Resource tags. + returned: always + type: dict + sample: { + "delete": "on-exit", + "testing": "testing" + } + public_ip_address_version: + description: + - The public IP address version. + - Possible values are C(IPv4) and C(IPv6). + returned: always + type: str + sample: IPv4 + ip_tags: + description: + - The list of tags associated with the public IP prefixes. + returned: always + type: list + sample: [ + { + "type": "FirstPartyUsage", + "value": "Storage" + } + ] + provisioning_state: + description: + - The provisioning state of the PublicIP Prefix resource. + - Possible values is C(Succeeded). + returned: always + type: str + sample: Succeeded + etag: + description: + - A unique read-only string that changes whenever the resource is updated. + returned: always + type: str + sample: "W/'1905ee13-7623-45b1-bc6b-4a12b2fb9d15'" + sku: + description: + - The public IP prefix SKU. + returned: always + type: dict + sample: {'name': 'standard', 'tier': 'Regional'} + zones: + description: + - A list of availability zones denoting the IP allocated for the resource needs to come from. + returned: always + type: list + sample: ['1', '2'] + prefix_length: + description: + - The Length of the Public IP Prefix. + type: int + returned: always + sample: 29 + extended_location: + description: + - The extended location of the public ip address. + type: str + returned: always + sample: 'eastus2' + custom_ip_prefix: + description: + - The customIpPrefix that this prefix is associated with. + type: dict + returned: always + sample: {} + public_ip_addresses: + description: + - The list of all referenced PublicIPAddresses. + type: list + sample: [] + resource_guid: + description: + - The resource GUID property of the public IP prefix resource. + type: str + sample: "47cafa04-851d-4579-894d-74ad6afe3233" + ip_prefix: + description: + - The allocated Prefix. + type: str + sample: 20.199.95.80/29 +''' +try: + from azure.core.exceptions import ResourceNotFoundError +except Exception: + # This is handled in azure_rm_common + pass + +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + +AZURE_OBJECT_CLASS = 'PublicIpPrefix' + + +class AzureRMPublicIPPrefixInfo(AzureRMModuleBase): + + def __init__(self): + + self.module_arg_spec = dict( + name=dict(type='str'), + resource_group=dict(type='str'), + tags=dict(type='list', elements='str') + ) + + self.results = dict( + changed=False, + ) + + self.name = None + self.resource_group = None + self.tags = None + + super(AzureRMPublicIPPrefixInfo, self).__init__(self.module_arg_spec, + supports_check_mode=True, + supports_tags=False, + facts_module=True) + + def exec_module(self, **kwargs): + for key in self.module_arg_spec: + setattr(self, key, kwargs[key]) + + result = [] + if self.name is not None and self.resource_group is not None: + result = self.get_item() + elif self.resource_group: + result = self.list_resource_group() + else: + result = self.list_all() + + raw = self.filter(result) + + self.results['publicipprefixes'] = self.format(raw) + + return self.results + + def format(self, raw): + return [self.prefix_to_dict(item) for item in raw] + + def filter(self, response): + return [item for item in response if self.has_tags(item.tags, self.tags)] + + def prefix_to_dict(self, prefix): + result = dict( + id=prefix.id, + name=prefix.name, + tags=prefix.tags, + type=prefix.type, + location=prefix.location, + public_ip_address_version=prefix.public_ip_address_version, + prefix_length=prefix.prefix_length, + provisioning_state=prefix.provisioning_state, + etag=prefix.etag, + zones=prefix.zones, + sku=dict(), + ip_tags=list(), + custom_ip_prefix=dict(), + ip_prefix=prefix.ip_prefix, + resource_guid=prefix.resource_guid, + public_ip_addresses=list(), + extended_location=prefix.extended_location + ) + if prefix.public_ip_addresses: + result['public_ip_addresses'] = [x.id for x in prefix.public_ip_addresses] + if prefix.sku: + result['sku']['name'] = prefix.sku.name + result['sku']['tier'] = prefix.sku.tier + if prefix.custom_ip_prefix: + result['custom_ip_prefix']['id'] = prefix.custom_ip_prefix.id + if prefix.ip_tags: + result['ip_tags'] = [dict(type=x.ip_tag_type, value=x.tag) for x in prefix.ip_tags] + return result + + def get_item(self): + self.log('Get properties for {0}'.format(self.name)) + item = None + try: + item = self.network_client.public_ip_prefixes.get(self.resource_group, self.name) + except ResourceNotFoundError: + pass + return [item] if item else [] + + def list_resource_group(self): + self.log('List items in resource groups') + try: + response = self.network_client.public_ip_prefixes.list(self.resource_group) + except ResourceNotFoundError as exc: + self.fail("Error listing items in resource groups {0} - {1}".format(self.resource_group, str(exc))) + return response + + def list_all(self): + self.log('List all items') + try: + response = self.network_client.public_ip_prefixes.list_all() + except ResourceNotFoundError as exc: + self.fail("Error listing all items - {0}".format(str(exc))) + return response + + +def main(): + AzureRMPublicIPPrefixInfo() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault.py index b2c45b2d5..818d846bf 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault.py @@ -208,7 +208,6 @@ class AzureRMRecoveryServicesVault(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_resource() @@ -247,10 +246,12 @@ class AzureRMRecoveryServicesVault(AzureRMModuleBaseExt): self.log('Error in creating Azure Recovery Service Vault.') self.fail('Error in creating Azure Recovery Service Vault {0}'.format(str(e))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault_info.py index 6b2dee776..bc26db2dd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_recoveryservicesvault_info.py @@ -12,9 +12,9 @@ DOCUMENTATION = \ --- module: azure_rm_recoveryservicesvault_info version_added: '1.1.0' -short_description: Get Azure Recovery Services vault Details +short_description: Get or list the Azure Recovery Services vault Details description: - - Get Azure Recovery Services vault Details. + - Get or list the Azure Recovery Services vault Details. options: resource_group: description: @@ -23,8 +23,8 @@ options: type: str name: description: + - If this parameter is not configured, all Vaults in the resource group are listed. - The name of the Azure Recovery Service Vault. - required: true type: str extends_documentation_fragment: - azure.azcollection.azure @@ -34,6 +34,10 @@ author: ''' EXAMPLES = ''' +- name: List all Azure Recovery Services Vault in same resource group + azure_rm_recoveryservicesvault_info: + resource_group: 'myResourceGroup' + - name: Get Azure Recovery Services Vault Details. azure_rm_recoveryservicesvault_info: resource_group: 'myResourceGroup' @@ -110,7 +114,6 @@ class AzureRMRecoveryServicesVaultInfo(AzureRMModuleBaseExt): ), name=dict( type='str', - required=True ) ) @@ -137,13 +140,21 @@ class AzureRMRecoveryServicesVaultInfo(AzureRMModuleBaseExt): return '2016-06-01' def get_url(self): - return '/subscriptions/' \ - + self.subscription_id \ - + '/resourceGroups/' \ - + self.resource_group \ - + '/providers/Microsoft.RecoveryServices' \ - + '/vaults' + '/' \ - + self.name + if self.name is not None: + return '/subscriptions/' \ + + self.subscription_id \ + + '/resourceGroups/' \ + + self.resource_group \ + + '/providers/Microsoft.RecoveryServices' \ + + '/vaults' + '/' \ + + self.name + else: + return '/subscriptions/' \ + + self.subscription_id \ + + '/resourceGroups/' \ + + self.resource_group \ + + '/providers/Microsoft.RecoveryServices' \ + + '/vaults' def exec_module(self, **kwargs): for key in list(self.module_arg_spec.keys()): @@ -160,10 +171,9 @@ class AzureRMRecoveryServicesVaultInfo(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) - changed = True + changed = False response = self.get_recovery_service_vault_info() self.results['response'] = response @@ -188,10 +198,12 @@ class AzureRMRecoveryServicesVaultInfo(AzureRMModuleBaseExt): self.log('Error in fetching Azure Recovery Service Vault Details.') self.fail('Error in fetching Azure Recovery Service Vault Details {0}'.format(str(e))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache.py index b93a52992..5a231cc3e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache.py @@ -510,8 +510,7 @@ class AzureRMRedisCaches(AzureRMModuleBase): # get management client self._client = self.get_mgmt_svc_client(RedisManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - api_version='2018-03-01', - is_track2=True) + api_version='2018-03-01') # set location resource_group = self.get_resource_group(self.resource_group) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache_info.py index 44e47f4d5..782fb0417 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscache_info.py @@ -269,8 +269,7 @@ class AzureRMRedisCacheInfo(AzureRMModuleBase): # get management client self._client = self.get_mgmt_svc_client(RedisManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - api_version='2018-03-01', - is_track2=True) + api_version='2018-03-01') if self.name: self.results['rediscaches'] = self.get_item() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscachefirewallrule.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscachefirewallrule.py index 67b2c90b6..b0fbdb43e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscachefirewallrule.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_rediscachefirewallrule.py @@ -176,8 +176,7 @@ class AzureRMRedisCacheFirewallRule(AzureRMModuleBase): # get management client self._client = self.get_mgmt_svc_client(RedisManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - api_version='2018-03-01', - is_track2=True) + api_version='2018-03-01') # check if the firewall rule exists old_response = self.get() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment.py index a70542f80..8cffc7999 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment.py @@ -141,11 +141,9 @@ class AzureRMRegistrationAssignment(AzureRMModuleBaseExt): ), properties=dict( type='dict', - disposition='/properties', options=dict( registration_definition_id=dict( type='str', - disposition='registration_definition_id', required=True ) ) @@ -188,7 +186,6 @@ class AzureRMRegistrationAssignment(AzureRMModuleBaseExt): self.mgmt_client = self.get_mgmt_svc_client(ManagedServicesClient, base_url=self._cloud_environment.endpoints.resource_manager, api_version='2019-09-01', - is_track2=True, suppress_subscription_id=True) old_response = self.get_resource() @@ -200,11 +197,9 @@ class AzureRMRegistrationAssignment(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): + if self.body.get('properties') is not None and \ + self.body['properties']['registration_definition_id'] != \ + old_response['properties']['registration_definition_id']: self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment_info.py index ef8875f7c..2dabe949e 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationassignment_info.py @@ -126,7 +126,6 @@ class AzureRMRegistrationAssignmentInfo(AzureRMModuleBase): self.mgmt_client = self.get_mgmt_svc_client(ManagedServicesClient, base_url=self._cloud_environment.endpoints.resource_manager, api_version='2020-09-01', - is_track2=True, suppress_subscription_id=True) if (self.scope is not None and self.registration_assignment_id is not None): @@ -168,12 +167,14 @@ class AzureRMRegistrationAssignmentInfo(AzureRMModuleBase): def format_item(self, item): if hasattr(item, 'as_dict'): return [item.as_dict()] - else: + elif item is not None: result = [] items = list(item) for tmp in items: result.append(tmp.as_dict()) return result + else: + return [] def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition.py index 0d89da3a9..0582df4cf 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition.py @@ -261,63 +261,51 @@ class AzureRMRegistrationDefinition(AzureRMModuleBaseExt): ), properties=dict( type='dict', - disposition='/properties', options=dict( description=dict( type='str', - disposition='description' ), authorizations=dict( type='list', - disposition='authorizations', required=True, elements='dict', options=dict( principal_id=dict( type='str', - disposition='principal_id', required=True ), role_definition_id=dict( type='str', - disposition='role_definition_id', required=True ) ) ), registration_definition_name=dict( type='str', - disposition='registration_definition_name' ), managed_by_tenant_id=dict( type='str', - disposition='managed_by_tenant_id', required=True ) ) ), plan=dict( type='dict', - disposition='/plan', options=dict( name=dict( type='str', - disposition='name', required=True ), publisher=dict( type='str', - disposition='publisher', required=True ), product=dict( type='str', - disposition='product', required=True ), version=dict( type='str', - disposition='version', required=True ) ) @@ -349,8 +337,6 @@ class AzureRMRegistrationDefinition(AzureRMModuleBaseExt): elif kwargs[key] is not None: self.body[key] = kwargs[key] - self.inflate_parameters(self.module_arg_spec, self.body, 0) - if self.registration_definition_id is None: self.registration_definition_id = str(uuid.uuid4()) @@ -365,7 +351,6 @@ class AzureRMRegistrationDefinition(AzureRMModuleBaseExt): self.mgmt_client = self.get_mgmt_svc_client(ManagedServicesClient, base_url=self._cloud_environment.endpoints.resource_manager, api_version='2019-09-01', - is_track2=True, suppress_subscription_id=True) old_response = self.get_resource() @@ -377,11 +362,16 @@ class AzureRMRegistrationDefinition(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): + if self.body.get('plan') is not None: + if old_response.get('plan') is not None and \ + not all(self.body['plan'][item] == old_response['plan'].get(item) + for item in self.body['plan'].keys()): + self.to_do = Actions.Update + else: + self.to_do = Actions.Update + elif (self.body.get('properties') is not None and + not all(self.body['properties'][item] == old_response['properties'].get(item) + for item in self.body['properties'].keys())): self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition_info.py index 1c095420c..cad5b8e2c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_registrationdefinition_info.py @@ -190,7 +190,6 @@ class AzureRMRegistrationDefinitionInfo(AzureRMModuleBase): self.mgmt_client = self.get_mgmt_svc_client(ManagedServicesClient, base_url=self._cloud_environment.endpoints.resource_manager, api_version='2019-09-01', - is_track2=True, suppress_subscription_id=True) if self.registration_definition_id is not None: @@ -223,12 +222,14 @@ class AzureRMRegistrationDefinitionInfo(AzureRMModuleBase): def format_item(self, item): if hasattr(item, 'as_dict'): return [item.as_dict()] - else: + elif item is not None: result = [] items = list(item) for tmp in items: result.append(tmp.as_dict()) return result + else: + return [] def main(): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource.py index a3a0544e2..4e786332f 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource.py @@ -325,7 +325,6 @@ class AzureRMResource(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.state == 'absent': @@ -416,10 +415,15 @@ class AzureRMResource(AzureRMModuleBase): self.polling_timeout, self.polling_interval) if self.state == 'present' and self.method != 'DELETE': - try: - response = json.loads(response.body()) - except Exception: + if hasattr(response, 'body'): + try: + response = json.loads(response.body()) + except Exception: + response = response.body() + elif hasattr(response, 'context'): response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) else: response = None diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource_info.py index eb5cd93e4..176be9531 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_resource_info.py @@ -76,6 +76,13 @@ options: description: - Subresource name. type: str + tags: + description: + - A dictionary of tags to filter on. + - Each key-value pair in the dictionary specifies a tag name and its value to filter on differente resources. + type: dict + required: false + default: {} extends_documentation_fragment: - azure.azcollection.azure @@ -98,6 +105,14 @@ EXAMPLES = ''' azure_rm_resource_info: resource_group: "{{ resource_group }}" resource_type: resources + +- name: Get all snapshots of all resource groups of a subscription but filtering with two tags. + azure_rm_resource_info: + provider: compute + resource_type: snapshots + tags: + enviroment: dev + department: hr ''' RETURN = ''' @@ -346,7 +361,8 @@ class AzureRMResourceInfo(AzureRMModuleBase): ), api_version=dict( type='str' - ) + ), + tags=dict(type='dict', default={}) ) # store the results of the module operation self.results = dict( @@ -370,7 +386,6 @@ class AzureRMResourceInfo(AzureRMModuleBase): for key in self.module_arg_spec: setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) if self.url is None: @@ -450,6 +465,12 @@ class AzureRMResourceInfo(AzureRMModuleBase): self.fail('Failed to parse response: ' + str(e)) if not skiptoken: break + if kwargs['tags']: + filtered_response = [] + for resource in self.results['response']: + if all(resource.get('tags', {}).get(tag_key) == tag_value for tag_key, tag_value in kwargs['tags'].items()): + filtered_response.append(resource) + self.results['response'] = filtered_response return self.results diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition.py index 8683142d8..86f085099 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition.py @@ -224,7 +224,6 @@ class AzureRMRoleDefinition(AzureRMModuleBase): # get management client self._client = self.get_mgmt_svc_client(AuthorizationManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version="2018-01-01-preview") self.scope = self.build_scope() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition_info.py index ce8ee238e..8f7c9ac4d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_roledefinition_info.py @@ -194,7 +194,6 @@ class AzureRMRoleDefinitionInfo(AzureRMModuleBase): # get management client self._client = self.get_mgmt_svc_client(AuthorizationManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version="2018-01-01-preview") if self.id: diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup.py index 8b25449ca..bf247e216 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_securitygroup.py @@ -44,8 +44,11 @@ options: type: str choices: - Udp + - UDP - Tcp + - TCP - Icmp + - ICMP - "*" default: "*" source_port_range: @@ -164,8 +167,11 @@ options: type: str choices: - Udp + - UDP - Tcp + - TCP - Icmp + - ICMP - "*" default: "*" source_port_range: @@ -722,7 +728,7 @@ def create_network_security_group_dict(nsg): rule_spec = dict( name=dict(type='str', required=True), description=dict(type='str'), - protocol=dict(type='str', choices=['Udp', 'Tcp', 'Icmp', '*'], default='*'), + protocol=dict(type='str', choices=['Udp', 'UDP', 'Tcp', 'TCP', 'Icmp', 'ICMP', '*'], default='*'), source_port_range=dict(type='raw', default='*'), destination_port_range=dict(type='raw', default='*'), source_address_prefix=dict(type='raw', default='*'), diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus_info.py index 5ccd4dea7..b736eb6c2 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_servicebus_info.py @@ -378,6 +378,25 @@ servicebuses: "type": "Microsoft.ServiceBus/Namespaces/Queues/AuthorizationRules" } } + private_endpoint_connections: + description: + - Properties of the PrivateEndpointConnection. + type: list + returned: always + sample: [{ + "id": "/subscriptions/xxxxxx/resourceGroups/myRG/providers/Microsoft.ServiceBus/namespaces/fredVM/privateEndpointConnections/xxxxxxxx", + "name": "xxxxxx", + "private_endpoint": { + "id": "/subscriptions/xxxxx/resourceGroups/myRG/providers/Microsoft.Network/privateEndpoints/fredprivateendpoint" + }, + "private_link_service_connection_state": { + "description": "Auto-Approved", + "status": "Approved" + }, + "provisioning_state": "Succeeded", + "type": "Microsoft.ServiceBus/Namespaces/PrivateEndpointConnections" + }] + ''' try: @@ -385,7 +404,6 @@ try: except Exception: # This is handled in azure_rm_common pass - from ansible.module_utils.common.dict_transformations import _camel_to_snake from ansible.module_utils._text import to_native from datetime import datetime, timedelta @@ -484,6 +502,8 @@ class AzureRMServiceBusInfo(AzureRMModuleBase): result[attribute] = to_native(value) elif attribute == 'max_size_in_megabytes': result['max_size_in_mb'] = value + elif attribute == 'private_endpoint_connections': + result['private_endpoint_connections'] = [item.as_dict() for item in value] else: result[attribute] = value if self.show_sas_policies and self.type != 'subscription': diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_snapshot.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_snapshot.py index bd3acd9bd..b3db0a0d7 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_snapshot.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_snapshot.py @@ -142,24 +142,17 @@ class AzureRMSnapshots(AzureRMModuleBaseExt): self.module_arg_spec = dict( resource_group=dict( type='str', - updatable=False, - disposition='resourceGroupName', required=True ), name=dict( type='str', - updatable=False, - disposition='snapshotName', required=True ), location=dict( - type='str', - updatable=False, - disposition='/' + type='str' ), sku=dict( type='dict', - disposition='/', options=dict( name=dict( type='str', @@ -174,29 +167,22 @@ class AzureRMSnapshots(AzureRMModuleBaseExt): ), os_type=dict( type='str', - disposition='/properties/osType', choices=['Windows', 'Linux'] ), incremental=dict(type='bool', default=False), creation_data=dict( type='dict', - disposition='/properties/creationData', options=dict( create_option=dict( type='str', - disposition='createOption', choices=['Import', 'Copy'], ), source_uri=dict( - type='str', - disposition='sourceUri', - purgeIfNone=True + type='str' ), source_id=dict( - type='str', - disposition='sourceResourceId', - purgeIfNone=True + type='str' ) ) ), @@ -233,22 +219,27 @@ class AzureRMSnapshots(AzureRMModuleBaseExt): supports_tags=True) def exec_module(self, **kwargs): - for key in list(self.module_arg_spec.keys()): + for key in list(self.module_arg_spec.keys()) + ['tags']: if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: if key == 'incremental': self.body['properties']['incremental'] = kwargs[key] + elif key == 'os_type': + self.body['properties']['osType'] = kwargs[key] + elif key == 'creation_data': + self.body['properties']['creationData'] = dict() + if kwargs[key].get('create_option') is not None: + self.body['properties']['creationData']['createOption'] = kwargs[key].get('create_option') + self.body['properties']['creationData']['sourceUri'] = kwargs[key].get('source_uri') + self.body['properties']['creationData']['sourceResourceId'] = kwargs[key].get('source_id') else: self.body[key] = kwargs[key] - self.inflate_parameters(self.module_arg_spec, self.body, 0) - old_response = None response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) resource_group = self.get_resource_group(self.resource_group) @@ -283,12 +274,22 @@ class AzureRMSnapshots(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - if not self.default_compare(modifiers, self.body, old_response, '', self.results): + if self.body.get('sku') is not None and \ + not all(self.body['sku'][item] == old_response['sku'].get(item) for item in self.body['sku'].keys()): + self.to_do = Actions.Update + if self.body['properties'].get('incremental') is not None and \ + self.body['properties']['incremental'] != old_response['properties']['incremental']: + self.to_do = Actions.Update + if self.body['properties'].get('osType') is not None and \ + self.body['properties']['osType'] != old_response['properties'].get('osType'): + self.to_do = Actions.Update + if self.body['properties'].get('creationData') is not None and \ + not all(self.body['properties']['creationData'][item] == old_response['properties']['creationData'].get(item) + for item in self.body['properties']['creationData'].keys()): + self.to_do = Actions.Update + + update_tags, self.body['tags'] = self.update_tags(old_response.get('tags')) + if update_tags: self.to_do = Actions.Update if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance.py index b59421062..631931afd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance.py @@ -262,7 +262,7 @@ sql_managed_instance: sample: "/subscription/xxx-xxx/resourceGroups/testRG/providers/Microsoft.Sql/managedInstances/fredsqlinstance" name: description: - - SQL manged instance name. + - SQL managed instance name. returned: always type: str sample: testmanagedinstance diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance_info.py index 5434cb6a4..3a85d00ac 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sqlmanagedinstance_info.py @@ -14,7 +14,7 @@ module: azure_rm_sqlmanagedinstance_info version_added: "0.15.0" short_description: Get Azure SQL managed instance facts description: - - Get facts of Azure SQL manged instance facts. + - Get facts of Azure SQL managed instance facts. options: resource_group: @@ -49,7 +49,7 @@ EXAMPLES = ''' azure_rm_sqlmanagedinstance_info: resource_group: testrg -- name: List SQL manged instance by subscription and filter by tags +- name: List SQL managed instance by subscription and filter by tags azure_rm_sqlmanagedinstance_info: tags: - foo @@ -70,7 +70,7 @@ sql_managed_instance: sample: "/subscription/xxx-xxx/resourceGroups/testRG/providers/Microsoft.Sql/managedInstances/fredsqlinstance" name: description: - - SQL manged instance name. + - SQL managed instance name. returned: always type: str sample: testmanagedinstance diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sshpublickey.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sshpublickey.py new file mode 100644 index 000000000..1c7a473b8 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sshpublickey.py @@ -0,0 +1,266 @@ +#!/usr/bin/python +# +# Copyright (c) 2023 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_sshpublickey +version_added: "2.0.0" +short_description: Manage ssh public key with vm +description: + - Create, update or delete the vm public key. +options: + resource_group: + description: + - Name of resource group. + required: true + type: str + location: + description: + - Valid Azure location. Defaults to location of the resource group. + type: str + name: + description: + - The name of the SSH public key. + required: true + type: str + public_key: + description: + - SSH public key used to authenticate to a virtual machine through ssh. + - If this property is not initially provided when the resource is created, the publicKey property will be populated when generateKeyPair is called. + - If the public key is provided upon resource creation, the provided public key needs to be at least 2048-bit and in ssh-rsa format. + type: str + state: + description: + - State of the SSH Public Key. Use C(present) to create or update and C(absent) to delete. + default: present + type: str + choices: + - absent + - present + +extends_documentation_fragment: + - azure.azcollection.azure + - azure.azcollection.azure_tags + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: Create a SSH Public Key + azure_rm_sshpublickey: + resource_group: myResourceGroup + name: mySshPublicKey + public_key: "ssh-rsa ****************************@test.com" + tags: + testing: testing + delete: on-exit + +- name: Generate a pair SSH Public Key + azure_rm_sshpublickey: + resource_group: myResourceGroup + name: mySshPublicKey + tags: + testing: testing + delete: on-exit + +- name: Delete a SSH Public Key + azure_rm_sshpublickey: + resource_group: myResourceGroup + name: mySshPublicKey + state: absent +''' +RETURN = ''' +state: + description: + - Current state of the SSH Public Key. + returned: always + type: complex + contains: + id: + description: + - Resource ID. + returned: always + type: str + sample: /subscriptions/xxxx/resourceGroups/xxx/providers/Microsoft.Compute/sshPublicKeys/mySshPublicKeyName + location: + description: + - The Geo-location where the resource lives. + returned: always + type: str + sample: eastus + name: + description: + - Resource name. + returned: always + type: str + sample: mySshPublicKey + tags: + description: + - Resource tags, such as { 'tags1':'value1' }. + returned: always + type: dict + sample: { 'key1':'value1' } + public_key: + description: + - SSH public key used to authenticate to a virtual machine through ssh. + returned: always + type: str + sample: "ssh-rsa **************@test.com" +''' + +try: + from azure.core.exceptions import ResourceNotFoundError +except ImportError: + # This is handled in azure_rm_common + pass + +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + + +class AzureRMSshPublicKey(AzureRMModuleBase): + + def __init__(self): + + self.module_arg_spec = dict( + resource_group=dict(type='str', required=True), + name=dict(type='str', required=True), + state=dict(type='str', default='present', choices=['present', 'absent']), + location=dict(type='str'), + public_key=dict(type='str'), + ) + + self.resource_group = None + self.name = None + self.state = None + self.location = None + self.public_key = None + + self.body = dict() + + self.results = dict( + changed=False, + state=dict() + ) + + super(AzureRMSshPublicKey, self).__init__(self.module_arg_spec, + supports_tags=True, + supports_check_mode=True) + + def exec_module(self, **kwargs): + + for key in list(self.module_arg_spec.keys()) + ['tags']: + setattr(self, key, kwargs[key]) + for key in ['tags', 'public_key']: + self.body[key] = kwargs[key] + + resource_group = self.get_resource_group(self.resource_group) + if not self.location: + # Set default location + self.location = resource_group.location + + changed = False + results = dict() + + old_response = self.get_by_name() + + if old_response is not None: + if self.state == 'present': + update_tags, self.body['tags'] = self.update_tags(old_response['tags']) + if update_tags or self.body['public_key'] is not None and self.body['public_key'] != old_response['public_key']: + changed = True + if not self.check_mode: + results = self.update_ssh_public_key(self.body) + else: + results = old_response + else: + changed = True + if not self.check_mode: + results = self.delete_ssh_public_key() + else: + if self.state == 'present': + changed = True + if not self.check_mode: + self.body['location'] = self.location + results = self.create_ssh_public_key(self.body) + else: + changed = False + self.log("The SSH Public Key is not exists") + + self.results['changed'] = changed + self.results['state'] = results + + return self.results + + def get_by_name(self): + response = None + try: + response = self.compute_client.ssh_public_keys.get(self.resource_group, self.name) + + except ResourceNotFoundError as exec: + self.log("Failed to get ssh public keys, Exception as {0}".format(exec)) + + return self.to_dict(response) + + def create_ssh_public_key(self, body): + response = None + try: + if body.get('public_key') is None: + response = self.to_dict(self.compute_client.ssh_public_keys.create(self.resource_group, self.name, body)) + response.update(self.to_dict(self.compute_client.ssh_public_keys.generate_key_pair(self.resource_group, self.name))) + else: + response = self.to_dict(self.compute_client.ssh_public_keys.create(self.resource_group, self.name, body)) + except Exception as exc: + self.fail("Error creating SSH Public Key {0} - {1}".format(self.name, str(exc))) + + return response + + def update_ssh_public_key(self, body): + response = None + try: + response = self.compute_client.ssh_public_keys.update(self.resource_group, self.name, body) + except Exception as exc: + self.fail("Error updating SSH Public Key {0} - {1}".format(self.name, str(exc))) + return self.to_dict(response) + + def delete_ssh_public_key(self): + try: + self.compute_client.ssh_public_keys.delete(self.resource_group, self.name) + except Exception as exc: + self.fail("Error deleting SSH Public Key {0} - {1}".format(self.name, str(exc))) + + def to_dict(self, body): + results = None + if body is not None: + if hasattr(body, 'private_key'): + results = dict( + private_key=body.private_key, + id=body.id, + public_key=body.public_key + ) + else: + results = dict( + id=body.id, + name=body.name, + location=body.location, + tags=body.tags, + public_key=body.public_key + ) + return results + + +def main(): + AzureRMSshPublicKey() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sshpublickey_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sshpublickey_info.py new file mode 100644 index 000000000..3a84f2e74 --- /dev/null +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_sshpublickey_info.py @@ -0,0 +1,196 @@ +#!/usr/bin/python +# +# Copyright (c) 2023 xuzhang3 (@xuzhang3), Fred-sun (@Fred-sun) +# +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = ''' +--- +module: azure_rm_sshpublickey_info + +version_added: "2.0.0" + +short_description: Get Ssh Public Key with VM facts + +description: + - Get Ssh Public Key with VM facts + +options: + resource_group: + description: + - Name of the resource group. + type: str + name: + description: + - Name of the SSH Public Key. + type: str + tags: + description: + - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'. + type: list + elements: str + +extends_documentation_fragment: + - azure.azcollection.azure + +author: + - xuzhang3 (@xuzhang3) + - Fred-sun (@Fred-sun) + +''' + +EXAMPLES = ''' +- name: Get facts of the VM's ssh public key by name + azure_rm_sshpublickey_info: + resource_group: myResourceGroup + name: mysshpublickey + +- name: Get facts of the VM's ssh public key by resource group + azure_rm_sshpublickey_info: + resource_group: myResourceGroup + +- name: Get facts by tags + azure_rm_sshpublickey_info: + resource_group: myResourceGroup + tags: + - testing + - foo:bar +''' + +RETURN = ''' +ssh_keys: + description: + - Current state of the SSH Public Key. + returned: always + type: complex + contains: + id: + description: + - Resource ID. + returned: always + type: str + sample: /subscriptions/xxxx/resourceGroups/xxx/providers/Microsoft.Compute/sshPublicKeys/mySshPublicKeyName + location: + description: + - The Geo-location where the resource lives. + returned: always + type: str + sample: eastus + name: + description: + - Resource name. + returned: always + type: str + sample: mySshPublicKey + tags: + description: + - Resource tags, such as { 'tags1':'value1' }. + returned: always + type: dict + sample: { 'key1':'value1' } + public_key: + description: + - SSH public key used to authenticate to a virtual machine through ssh. + returned: always + type: str + sample: "ssh-rsa **************@test.com" +''' + +try: + from azure.core.exceptions import ResourceNotFoundError +except Exception: + # This is handled in azure_rm_common + pass + +from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase + + +class AzureRMSshPublicKeyInfo(AzureRMModuleBase): + + def __init__(self): + + self.module_arg_spec = dict( + resource_group=dict(type='str'), + name=dict(type='str'), + tags=dict(type='list', elements='str') + ) + + self.results = dict( + changed=False, + ssh_keys=[] + ) + + self.resource_group = None + self.name = None + self.tags = None + + super(AzureRMSshPublicKeyInfo, self).__init__(self.module_arg_spec, + supports_check_mode=True, + supports_tags=False, + facts_module=True) + + def exec_module(self, **kwargs): + for key in self.module_arg_spec: + setattr(self, key, kwargs[key]) + + if self.name and self.resource_group: + response = [self.get_by_name()] + elif self.resource_group: + response = self.list_by_resourcegroup() + else: + response = self.list_all() + + self.results['ssh_keys'] = [self.to_dict(item) for item in response if response is not None] + + return self.results + + def get_by_name(self): + response = None + try: + response = self.compute_client.ssh_public_keys.get(self.resource_group, self.name) + + except ResourceNotFoundError as exec: + self.log("Failed to get ssh public keys, Exception as {0}".format(exec)) + + return response + + def list_by_resourcegroup(self): + response = None + try: + response = self.compute_client.ssh_public_keys.list_by_resource_group(self.resource_group) + except Exception as exec: + self.log("Faild to list ssh public keys by resource group, exception as {0}".format(exec)) + return response + + def list_all(self): + response = None + try: + response = self.compute_client.ssh_public_keys.list_by_subscription() + except Exception as exc: + self.fail("Failed to list all items - {0}".format(str(exc))) + + return response + + def to_dict(self, body): + results = dict() + if body is not None and self.has_tags(body.tags, self.tags): + results = dict( + id=body.id, + name=body.name, + location=body.location, + tags=body.tags, + public_key=body.public_key + ) + return results + + +def main(): + AzureRMSshPublicKeyInfo() + + +if __name__ == '__main__': + main() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount.py index c7c280ef4..42c5b2e42 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount.py @@ -87,6 +87,10 @@ options: - Account HierarchicalNamespace enabled if sets to true. - When I(is_hns_enabled=True), I(kind) cannot be C(Storage). type: bool + enable_nfs_v3: + description: + - NFS 3.0 protocol. + type: bool access_tier: description: - The access tier for this storage account. Required when I(kind=BlobStorage). @@ -240,6 +244,13 @@ options: description: - The absolute path of the custom 404 page. type: str + large_file_shares_state: + description: + - Allow large file shares if sets to Enabled. + type: str + choices: + - Enabled + - Disabled encryption: description: - The encryption settings on the storage account. @@ -333,6 +344,16 @@ EXAMPLES = ''' tags: testing: testing +- name: Create storage account with I(enable_nfs_v3=false) + azure_rm_storageaccount: + resource_group: myResourceGroup + name: c1h0002 + account_type: Premium_LRS + kind: FileStorage + enable_nfs_v3: false + static_website: + enabled: true + - name: configure firewall and virtual networks azure_rm_storageaccount: resource_group: myResourceGroup @@ -462,6 +483,12 @@ state: type: bool returned: always sample: true + enable_nfs_v3: + description: + - NFS 3.0 protocol. + type: bool + returned: always + sample: false location: description: - Valid Azure location. Defaults to location of the resource group. @@ -599,6 +626,12 @@ state: returned: always type: str sample: "Microsoft.Storage/storageAccounts" + large_file_shares_state: + description: + - Allow large file shares if sets to Enabled. + type: str + returned: always + sample: Enabled static_website: description: - Static website configuration for the storage account. @@ -711,6 +744,8 @@ class AzureRMStorageAccount(AzureRMModuleBase): blob_cors=dict(type='list', options=cors_rule_spec, elements='dict'), static_website=dict(type='dict', options=static_website_spec), is_hns_enabled=dict(type='bool'), + large_file_shares_state=dict(type='str', choices=['Enabled', 'Disabled']), + enable_nfs_v3=dict(type='bool'), encryption=dict( type='dict', options=dict( @@ -766,6 +801,8 @@ class AzureRMStorageAccount(AzureRMModuleBase): self.static_website = None self.encryption = None self.is_hns_enabled = None + self.large_file_shares_state = None + self.enable_nfs_v3 = None super(AzureRMStorageAccount, self).__init__(self.module_arg_spec, supports_check_mode=True) @@ -870,6 +907,8 @@ class AzureRMStorageAccount(AzureRMModuleBase): allow_blob_public_access=account_obj.allow_blob_public_access, network_acls=account_obj.network_rule_set, is_hns_enabled=account_obj.is_hns_enabled if account_obj.is_hns_enabled else False, + enable_nfs_v3=account_obj.enable_nfs_v3 if hasattr(account_obj, 'enable_nfs_v3') else None, + large_file_shares_state=account_obj.large_file_shares_state, static_website=dict( enabled=False, index_document=None, @@ -1020,6 +1059,10 @@ class AzureRMStorageAccount(AzureRMModuleBase): self.results['changed'] = True self.update_network_rule_set() + if self.enable_nfs_v3 is not None and bool(self.enable_nfs_v3) != bool(self.account_dict.get('enable_nfs_v3')): + self.results['changed'] = True + self.account_dict['enable_nfs_v3'] = self.enable_nfs_v3 + if self.is_hns_enabled is not None and bool(self.is_hns_enabled) != bool(self.account_dict.get('is_hns_enabled')): self.results['changed'] = True self.account_dict['is_hns_enabled'] = self.is_hns_enabled @@ -1129,6 +1172,21 @@ class AzureRMStorageAccount(AzureRMModuleBase): except Exception as exc: self.fail("Failed to update access tier: {0}".format(str(exc))) + if self.large_file_shares_state is not None: + if self.large_file_shares_state != self.account_dict['large_file_shares_state']: + self.results['changed'] = True + self.account_dict['large_file_shares_state'] = self.large_file_shares_state + + if self.results['changed'] and not self.check_mode: + if self.large_file_shares_state == 'Disabled': + parameters = self.storage_models.StorageAccountUpdateParameters(large_file_shares_state=None) + else: + parameters = self.storage_models.StorageAccountUpdateParameters(large_file_shares_state=self.large_file_shares_state) + try: + self.storage_client.storage_accounts.update(self.resource_group, self.name, parameters) + except Exception as exc: + self.fail("Failed to update large_file_shares_state: {0}".format(str(exc))) + update_tags, self.account_dict['tags'] = self.update_tags(self.account_dict['tags']) if update_tags: self.results['changed'] = True @@ -1198,6 +1256,8 @@ class AzureRMStorageAccount(AzureRMModuleBase): allow_blob_public_access=self.allow_blob_public_access, encryption=self.encryption, is_hns_enabled=self.is_hns_enabled, + enable_nfs_v3=self.enable_nfs_v3, + large_file_shares_state=self.large_file_shares_state, tags=dict() ) if self.tags: @@ -1223,7 +1283,9 @@ class AzureRMStorageAccount(AzureRMModuleBase): allow_blob_public_access=self.allow_blob_public_access, encryption=self.encryption, is_hns_enabled=self.is_hns_enabled, - access_tier=self.access_tier) + enable_nfs_v3=self.enable_nfs_v3, + access_tier=self.access_tier, + large_file_shares_state=self.large_file_shares_state) self.log(str(parameters)) try: poller = self.storage_client.storage_accounts.begin_create(self.resource_group, self.name, parameters) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount_info.py index 75f179b6f..a530459dd 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageaccount_info.py @@ -211,6 +211,12 @@ storageaccounts: type: bool returned: always sample: true + enable_nfs_v3: + description: + - NFS 3.0 protocol. + type: bool + returned: always + sample: false kind: description: - The kind of storage. @@ -509,6 +515,12 @@ storageaccounts: returned: always type: dict sample: { "tag1": "abc" } + large_file_shares_state: + description: + - Allow large file shares if sets to Enabled. + type: str + returned: always + sample: Enabled static_website: description: - Static website configuration for the storage account. @@ -674,6 +686,8 @@ class AzureRMStorageAccountInfo(AzureRMModuleBase): public_network_access=account_obj.public_network_access, allow_blob_public_access=account_obj.allow_blob_public_access, is_hns_enabled=account_obj.is_hns_enabled if account_obj.is_hns_enabled else False, + large_file_shares_state=account_obj.large_file_shares_state, + enable_nfs_v3=account_obj.enable_nfs_v3 if hasattr(account_obj, 'enable_nfs_v3') else None, static_website=dict( enabled=False, index_document=None, diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageblob.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageblob.py index 868069f42..ad54b8422 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageblob.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_storageblob.py @@ -22,6 +22,17 @@ description: - the module can work exclusively in three modes, when C(batch_upload_src) is set, it is working in batch upload mode; when C(src) is set, it is working in upload mode and when C(dst) is set, it is working in dowload mode. options: + auth_mode: + description: + - The mode in which to run the command. C(login) mode will directly use your login credentials for the authentication. + - The legacy C(key) mode will attempt to query for an account key if no authentication parameters for the account are provided. + - Can also be set via the environment variable C(AZURE_STORAGE_AUTH_MODE). + default: key + type: str + choices: + - key + - login + version_added: "1.19.0" storage_account_name: description: - Name of the storage account to use. @@ -214,6 +225,7 @@ except ImportError: pass from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase +from ansible.module_utils.basic import env_fallback class AzureRMStorageBlob(AzureRMModuleBase): @@ -221,6 +233,12 @@ class AzureRMStorageBlob(AzureRMModuleBase): def __init__(self): self.module_arg_spec = dict( + auth_mode=dict( + type='str', + choices=['key', 'login'], + fallback=(env_fallback, ['AZURE_STORAGE_AUTH_MODE']), + default="key" + ), storage_account_name=dict(required=True, type='str', aliases=['account_name', 'storage_account']), blob=dict(type='str', aliases=['blob_name']), blob_type=dict(type='str', default='block', choices=['block', 'page']), @@ -281,7 +299,7 @@ class AzureRMStorageBlob(AzureRMModuleBase): # add file path validation - self.blob_service_client = self.get_blob_service_client(self.resource_group, self.storage_account_name) + self.blob_service_client = self.get_blob_service_client(self.resource_group, self.storage_account_name, self.auth_mode) self.container_obj = self.get_container() if self.blob: self.blob_obj = self.get_blob() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet.py index ec7117c37..3fbe2b803 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_subnet.py @@ -124,6 +124,7 @@ options: required: True type: str choices: + - Microsoft.ContainerService/managedClusters - Microsoft.Web/serverFarms - Microsoft.ContainerInstance/containerGroups - Microsoft.Netapp/volumes @@ -352,7 +353,8 @@ delegations_spec = dict( 'Microsoft.DBforPostgreSQL/serversv2', 'Microsoft.AzureCosmosDB/clusters', 'Microsoft.MachineLearningServices/workspaces', 'Microsoft.DBforPostgreSQL/singleServers', 'Microsoft.DBforPostgreSQL/flexibleServers', 'Microsoft.DBforMySQL/serversv2', 'Microsoft.DBforMySQL/flexibleServers', 'Microsoft.ApiManagement/service', 'Microsoft.Synapse/workspaces', - 'Microsoft.PowerPlatform/vnetaccesslinks', 'Microsoft.Network/managedResolvers', 'Microsoft.Kusto/clusters'] + 'Microsoft.PowerPlatform/vnetaccesslinks', 'Microsoft.Network/managedResolvers', 'Microsoft.Kusto/clusters', + 'Microsoft.ContainerService/managedClusters'] ), actions=dict( type='list', diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine.py index 35435b821..e845e2fa1 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine.py @@ -229,6 +229,10 @@ options: description: - Size of OS disk in GB. type: int + os_disk_encryption_set: + description: + - ID of disk encryption set for OS disk. + type: str os_type: description: - Base type of operating system. @@ -245,7 +249,7 @@ options: data_disks: description: - Describes list of data disks. - - Use M(azure.azcollection.azure_rm_mangeddisk) to manage the specific disk. + - Use M(azure.azcollection.azure_rm_manageddisk) to manage the specific disk. type: list elements: dict suboptions: @@ -262,6 +266,10 @@ options: - Size can be changed only when the virtual machine is deallocated. - Not sure when I(managed_disk_id) defined. type: int + disk_encryption_set: + description: + - ID of disk encryption set for data disk. + type: str managed_disk_type: description: - Managed data disk type. @@ -409,6 +417,7 @@ options: zones: description: - A list of Availability Zones for your VM. + - A maximum of one zone can be configured. type: list elements: str license_type: @@ -569,6 +578,33 @@ options: description: - Specifies whether vTPM should be enabled on the virtual machine. type: bool + swap_os_disk: + description: + - The swap OS disk parameters. + type: dict + suboptions: + os_disk_id: + description: + - The swap OS disk's ID. + type: str + os_disk_name: + description: + - The swap OS disk's name. + type: str + os_disk_resource_group: + description: + - The swap OS disk's resource group. + type: str + additional_capabilities: + description: + - Enables or disables a capability on the virtual machine. + type: dict + suboptions: + ultra_ssd_enabled: + description: + - The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM. + - Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine set only if this property is enabled. + type: bool extends_documentation_fragment: - azure.azcollection.azure @@ -760,6 +796,26 @@ EXAMPLES = ''' sku: '7.1' version: latest +- name: Update VM to swap OS disk + azure_rm_virtualmachine: + resource_group: "{{ resource_group }}" + name: "vmforimage{{ rpfx }}" + admin_username: testuser + ssh_password_enabled: false + managed_disk_type: Premium_LRS + ssh_public_keys: + - path: /home/testuser/.ssh/authorized_keys + key_data: "ssh-rsa *******************@qq.com" + vm_size: Standard_D4s_v3 + swap_os_disk: + os_disk_name: "{{ os_disk_name }}" + os_disk_resource_group: "{{ os_disk_resource_group }}" + image: + offer: 0001-com-ubuntu-server-focal + publisher: Canonical + sku: 20_04-lts + version: latest + - name: Power Off azure_rm_virtualmachine: resource_group: myResourceGroup @@ -856,6 +912,9 @@ azure_vm: type: dict sample: { "properties": { + "additional_capabilities": { + "ultra_ssd_enabled": false + }, "availabilitySet": { "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroup/myResourceGroup/providers/Microsoft.Compute/availabilitySets/MYAVAILABILITYSET" }, @@ -1088,6 +1147,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): storage_blob_name=dict(type='str', aliases=['storage_blob']), os_disk_caching=dict(type='str', aliases=['disk_caching'], choices=['ReadOnly', 'ReadWrite']), os_disk_size_gb=dict(type='int'), + os_disk_encryption_set=dict(type='str'), managed_disk_type=dict(type='str', choices=['Standard_LRS', 'StandardSSD_LRS', 'StandardSSD_ZRS', 'Premium_LRS', 'Premium_ZRS', 'UltraSSD_LRS']), os_disk_name=dict(type='str'), proximity_placement_group=dict(type='dict', options=proximity_placement_group_spec), @@ -1106,18 +1166,27 @@ class AzureRMVirtualMachine(AzureRMModuleBase): started=dict(type='bool'), force=dict(type='bool', default=False), generalized=dict(type='bool', default=False), + swap_os_disk=dict( + type='dict', + options=dict( + os_disk_resource_group=dict(type='str'), + os_disk_name=dict(type='str'), + os_disk_id=dict(type='str') + ) + ), data_disks=dict( type='list', elements='dict', options=dict( lun=dict(type='int', required=True), disk_size_gb=dict(type='int'), + disk_encryption_set=dict(type='str'), managed_disk_type=dict(type='str', choices=['Standard_LRS', 'StandardSSD_LRS', 'StandardSSD_ZRS', 'Premium_LRS', 'Premium_ZRS', 'UltraSSD_LRS']), storage_account_name=dict(type='str'), storage_container_name=dict(type='str', default='vhds'), storage_blob_name=dict(type='str'), - caching=dict(type='str', choices=['ReadOnly', 'ReadOnly']) + caching=dict(type='str', choices=['ReadOnly', 'ReadWrite']) ) ), plan=dict(type='dict'), @@ -1149,6 +1218,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase): windows_config=dict(type='dict', options=windows_configuration_spec), linux_config=dict(type='dict', options=linux_configuration_spec), security_profile=dict(type='dict'), + additional_capabilities=dict( + type='dict', + options=dict( + ultra_ssd_enabled=dict(type='bool') + ) + ) ) self.resource_group = None @@ -1172,6 +1247,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): self.os_type = None self.os_disk_caching = None self.os_disk_size_gb = None + self.os_disk_encryption_set = None self.managed_disk_type = None self.os_disk_name = None self.proximity_placement_group = None @@ -1201,6 +1277,8 @@ class AzureRMVirtualMachine(AzureRMModuleBase): self.linux_config = None self.windows_config = None self.security_profile = None + self.additional_capabilities = None + self.swap_os_disk = None self.results = dict( changed=False, @@ -1209,8 +1287,10 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ansible_facts=dict(azure_vm=None) ) + required_if = [('os_disk_encryption_set', '*', ['managed_disk_type'])] + super(AzureRMVirtualMachine, self).__init__(derived_arg_spec=self.module_arg_spec, - supports_check_mode=True) + supports_check_mode=True, required_if=required_if) @property def boot_diagnostics_present(self): @@ -1277,12 +1357,16 @@ class AzureRMVirtualMachine(AzureRMModuleBase): vm_dict = None image_reference = None custom_image = False + swap_os_disk_flag = False resource_group = self.get_resource_group(self.resource_group) if not self.location: # Set default location self.location = resource_group.location + if self.swap_os_disk is not None: + swap_os_disk = self.get_os_disk(self.swap_os_disk) + self.location = normalize_location_name(self.location) if self.state == 'present': @@ -1411,6 +1495,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase): vm_dict['network_profile']['network_interfaces'] = updated_nics changed = True + if self.swap_os_disk is not None and swap_os_disk.get('name') != vm_dict['storage_profile']['os_disk']['name']: + self.log('CHANGED: Swap virtual machine {0} - OS disk name'.format(self.name)) + differences.append('Swap OS Disk') + changed = True + swap_os_disk_flag = True + if self.os_disk_caching and \ self.os_disk_caching != vm_dict['storage_profile']['os_disk']['caching']: self.log('CHANGED: virtual machine {0} - OS disk caching'.format(self.name)) @@ -1448,7 +1538,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): self.log('CHANGED: virtual machine {0} - short hostname'.format(self.name)) differences.append('Short Hostname') changed = True - vm_dict['os_orofile']['computer_name'] = self.short_hostname + vm_dict['os_profile']['computer_name'] = self.short_hostname if self.started and vm_dict['powerstate'] not in ['starting', 'running'] and self.allocated: self.log("CHANGED: virtual machine {0} not running and requested state 'running'".format(self.name)) @@ -1479,7 +1569,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): differences.append('Zones') changed = True - if self.license_type is not None and vm_dict.get('licenseType') != self.license_type: + if self.license_type is not None and vm_dict.get('license_type') != self.license_type: differences.append('License Type') changed = True @@ -1516,7 +1606,7 @@ class AzureRMVirtualMachine(AzureRMModuleBase): if self.security_profile is not None: update_security_profile = False - if 'securityProfile' not in vm_dict.keys(): + if 'security_profile' not in vm_dict.keys(): update_security_profile = True differences.append('security_profile') else: @@ -1547,6 +1637,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase): changed = True differences.append('security_profile') + if self.additional_capabilities is not None: + if 'additional_capabilities' not in vm_dict.keys() or\ + bool(self.additional_capabilities['ultra_ssd_enabled']) != bool(vm_dict['additional_capabilities']['ultra_ssd_enabled']): + changed = True + differences.append('additional_capabilities') + if self.windows_config is not None and vm_dict['os_profile'].get('windows_configuration') is not None: if self.windows_config['enable_automatic_updates'] != vm_dict['os_profile']['windows_configuration']['enable_automatic_updates']: self.fail("(PropertyChangeNotAllowed) Changing property 'windowsConfiguration.enableAutomaticUpdates' is not allowed.") @@ -1559,6 +1655,11 @@ class AzureRMVirtualMachine(AzureRMModuleBase): vm_dict['os_profile']['linux_configuration']['disable_password_authentication']: self.fail("(PropertyChangeNotAllowed) Changing property 'linuxConfiguration.disablePasswordAuthentication' is not allowed.") + current_os_des_id = vm_dict['storage_profile'].get('os_disk', {}).get('managed_disk', {}).get('disk_encryption_set', {}).get('id', None) + if self.os_disk_encryption_set is not None and current_os_des_id is not None: + if self.os_disk_encryption_set != current_os_des_id: + self.fail("(PropertyChangeNotAllowed) Changing property 'storage_profile.os_disk.managed_disk.disk_encryption_set' is not allowed.") + # Defaults for boot diagnostics if 'diagnostics_profile' not in vm_dict: vm_dict['diagnostics_profile'] = {} @@ -1601,6 +1702,29 @@ class AzureRMVirtualMachine(AzureRMModuleBase): vm_dict['tags']['_own_sa_'] = own_sa changed = True + if self.proximity_placement_group is not None: + if vm_dict.get('proximity_placement_group') is None: + changed = True + differences.append('proximity_placement_group') + if self.proximity_placement_group.get('name') is not None and self.proximity_placement_group.get('resource_group') is not None: + proximity_placement_group = self.get_proximity_placement_group(self.proximity_placement_group.get('resource_group'), + self.proximity_placement_group.get('name')) + self.proximity_placement_group['id'] = proximity_placement_group.id + + elif self.proximity_placement_group.get('id') is not None: + if vm_dict['proximity_placement_group'].get('id', "").lower() != self.proximity_placement_group['id'].lower(): + changed = True + differences.append('proximity_placement_group') + elif self.proximity_placement_group.get('name') is not None and self.proximity_placement_group.get('resource_group') is not None: + proximity_placement_group = self.get_proximity_placement_group(self.proximity_placement_group.get('resource_group'), + self.proximity_placement_group.get('name')) + if vm_dict['proximity_placement_group'].get('id', "").lower() != proximity_placement_group.id.lower(): + changed = True + differences.append('proximity_placement_group') + self.proximity_placement_group['id'] = proximity_placement_group.id + else: + self.fail("Parameter error: Please recheck your proximity placement group ") + self.differences = differences elif self.state == 'absent': @@ -1700,6 +1824,11 @@ class AzureRMVirtualMachine(AzureRMModuleBase): vhd = self.compute_models.VirtualHardDisk(uri=requested_vhd_uri) managed_disk = None + if managed_disk and self.os_disk_encryption_set: + managed_disk.disk_encryption_set = self.compute_models.DiskEncryptionSetParameters( + id=self.os_disk_encryption_set + ) + plan = None if self.plan: plan = self.compute_models.Plan(name=self.plan.get('name'), product=self.plan.get('product'), @@ -1865,6 +1994,10 @@ class AzureRMVirtualMachine(AzureRMModuleBase): else: data_disk_vhd = None data_disk_managed_disk = self.compute_models.ManagedDiskParameters(storage_account_type=data_disk['managed_disk_type']) + if data_disk.get('disk_encryption_set'): + data_disk_managed_disk.disk_encryption_set = self.compute_models.DiskEncryptionSetParameters( + id=data_disk['disk_encryption_set'] + ) disk_name = self.name + "-datadisk-" + str(count) count += 1 @@ -1916,6 +2049,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ) vm_resource.security_profile = security_profile + if self.additional_capabilities is not None: + additional_capabilities = self.compute_models.AdditionalCapabilities( + ultra_ssd_enabled=self.additional_capabilities.get('ultra_ssd_enabled') + ) + vm_resource.additional_capabilities = additional_capabilities + self.log("Create virtual machine with parameters:") self.create_or_update_vm(vm_resource, 'all_autocreated' in self.remove_on_absent) @@ -1938,11 +2077,18 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ) proximity_placement_group_resource = None - try: - proximity_placement_group_resource = self.compute_models.SubResource(id=vm_dict['proximity_placement_group'].get('id')) - except Exception: - # pass if the proximity Placement Group - pass + if self.proximity_placement_group is not None: + try: + proximity_placement_group_resource = self.compute_models.SubResource(id=self.proximity_placement_group.get('id')) + except Exception: + # pass if the proximity Placement Group + pass + else: + try: + proximity_placement_group_resource = self.compute_models.SubResource(id=vm_dict['proximity_placement_group'].get('id')) + except Exception: + # pass if the proximity Placement Group + pass availability_set_resource = None try: @@ -1984,7 +2130,24 @@ class AzureRMVirtualMachine(AzureRMModuleBase): hardware_profile=self.compute_models.HardwareProfile( vm_size=vm_dict['hardware_profile'].get('vm_size') ), - storage_profile=self.compute_models.StorageProfile( + availability_set=availability_set_resource, + proximity_placement_group=proximity_placement_group_resource, + network_profile=self.compute_models.NetworkProfile( + network_interfaces=nics + ) + ) + + if swap_os_disk_flag: + storage_profile = self.compute_models.StorageProfile( + os_disk=self.compute_models.OSDisk( + name=swap_os_disk.get('name'), + managed_disk=swap_os_disk.get('managed_disk'), + create_option=vm_dict['storage_profile']['os_disk'].get('create_option'), + ), + image_reference=image_reference + ) + else: + storage_profile = self.compute_models.StorageProfile( os_disk=self.compute_models.OSDisk( name=vm_dict['storage_profile']['os_disk'].get('name'), vhd=vhd, @@ -1995,13 +2158,9 @@ class AzureRMVirtualMachine(AzureRMModuleBase): disk_size_gb=vm_dict['storage_profile']['os_disk'].get('disk_size_gb') ), image_reference=image_reference - ), - availability_set=availability_set_resource, - proximity_placement_group=proximity_placement_group_resource, - network_profile=self.compute_models.NetworkProfile( - network_interfaces=nics ) - ) + + vm_resource.storage_profile = storage_profile if self.license_type is not None: vm_resource.license_type = self.license_type @@ -2083,8 +2242,8 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ) else: vm_resource.os_profile.windows_configuration = self.compute_models.WindowsConfiguration( - provision_vm_agent=windows_config.get('provisionVMAgent', True), - enable_automatic_updates=windows_config.get('enableAutomaticUpdates', True) + provision_vm_agent=windows_config.get('provision_vm_agent', True), + enable_automatic_updates=windows_config.get('enable_automatic_updates', True) ) # Add linux configuration, if applicable @@ -2100,12 +2259,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ) ssh_config = linux_config.get('ssh', None) if ssh_config: - public_keys = ssh_config.get('publicKeys') + public_keys = ssh_config.get('public_keys') if public_keys: vm_resource.os_profile.linux_configuration.ssh = self.compute_models.SshConfiguration(public_keys=[]) for key in public_keys: vm_resource.os_profile.linux_configuration.ssh.public_keys.append( - self.compute_models.SshPublicKey(path=key['path'], key_data=key['keyData']) + self.compute_models.SshPublicKey(path=key['path'], key_data=key['key_data']) ) # data disk @@ -2116,6 +2275,10 @@ class AzureRMVirtualMachine(AzureRMModuleBase): if data_disk.get('managed_disk'): managed_disk_type = data_disk['managed_disk'].get('storage_account_type') data_disk_managed_disk = self.compute_models.ManagedDiskParameters(storage_account_type=managed_disk_type) + if data_disk.get('disk_encryption_set'): + data_disk_managed_disk.disk_encryption_set = self.compute_models.DiskEncryptionSetParameters( + id=data_disk['disk_encryption_set'] + ) data_disk_vhd = None else: data_disk_vhd = data_disk['vhd']['uri'] @@ -2146,6 +2309,12 @@ class AzureRMVirtualMachine(AzureRMModuleBase): ) vm_resource.security_profile = security_profile + if self.additional_capabilities is not None: + additional_capabilities = self.compute_models.AdditionalCapabilities( + ultra_ssd_enabled=self.additional_capabilities.get('ultra_ssd_enabled') + ) + vm_resource.additional_capabilities = additional_capabilities + self.log("Update virtual machine with parameters:") self.create_or_update_vm(vm_resource, False) @@ -2182,6 +2351,32 @@ class AzureRMVirtualMachine(AzureRMModuleBase): return self.results + def get_os_disk(self, os_disk): + resource_group_name = None + os_disk_name = None + if os_disk.get('os_disk_id') is not None: + os_disk_dict = self.parse_resource_to_dict(os_disk.get('os_disk_id')) + os_disk_name = os_disk_dict.get('name') + resource_group_name = os_disk_dict.get('resource_group') + elif os_disk.get('os_disk_resource_group') is not None and os_disk.get('os_disk_name') is not None: + os_disk_name = os_disk.get('os_disk_name') + resource_group_name = os_disk.get('os_disk_resource_group') + elif os_disk.get('os_disk_name') is not None: + os_disk_name = os_disk.get('name') + resource_group_name = self.resource_group + else: + self.fail("The swap_os_disk must contain one of 'os_disk_name' and 'os_disk_id'") + + try: + os_disk = {} + response = self.compute_client.disks.get(resource_group_name, os_disk_name) + os_disk['name'] = response.name + os_disk['managed_disk'] = dict(id=response.id) + os_disk['create_option'] = response.creation_data.create_option + return os_disk + except Exception as ec: + self.fail('Could not find os disk {0} in resource group {1}'.format(os_disk_name, resource_group_name)) + def get_vm(self): ''' Get the VM with expanded instanceView @@ -2189,7 +2384,23 @@ class AzureRMVirtualMachine(AzureRMModuleBase): :return: VirtualMachine object ''' try: + retry_count = 0 vm = self.compute_client.virtual_machines.get(self.resource_group, self.name, expand='instanceview') + while True: + if retry_count == 20: + self.fail("Error {0} has a provisioning state of Updating. Expecting state to be Successed.".format(self.name)) + + if vm.provisioning_state != 'Succeeded': + retry_count = retry_count + 1 + time.sleep(150) + vm = self.compute_client.virtual_machines.get(self.resource_group, self.name, expand='instanceview') + else: + p_state = None + for s in vm.instance_view.statuses: + if s.code.startswith('PowerState'): + p_state = s.code + if p_state is not None: + break return vm except Exception as exc: self.fail("Error getting virtual machine {0} - {1}".format(self.name, str(exc))) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine_info.py index d94f9848e..3df8e2fbc 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachine_info.py @@ -70,6 +70,12 @@ vms: returned: always type: complex contains: + additional_capabilities: + description: + - Enables or disables a capability on the virtual machine. + type: dict + returned: always + sample: {ultra_ssd_enabled: False} admin_username: description: - Administrator user name. @@ -244,6 +250,12 @@ vms: returned: always type: dict sample: { "key1":"value1" } + vm_agent_version: + description: + - Version of the Azure VM Agent (waagent) running inside the VM. + returned: always + type: str + sample: '2.9.1.1' vm_size: description: - Virtual machine size. @@ -459,6 +471,11 @@ class AzureRMVirtualMachineInfo(AzureRMModuleBase): new_result = {} + if instance.get('vm_agent') is not None: + new_result['vm_agent_version'] = instance['vm_agent'].get('vm_agent_version') + else: + new_result['vm_agent_version'] = 'Unknown' + if vm.security_profile is not None: new_result['security_profile'] = dict() if vm.security_profile.encryption_at_host is not None: @@ -483,6 +500,7 @@ class AzureRMVirtualMachineInfo(AzureRMModuleBase): new_result['vm_size'] = result['hardware_profile']['vm_size'] new_result['proximityPlacementGroup'] = result.get('proximity_placement_group') new_result['zones'] = result.get('zones', None) + new_result['additional_capabilities'] = result.get('additional_capabilities') os_profile = result.get('os_profile') if os_profile is not None: new_result['admin_username'] = os_profile.get('admin_username') diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset.py index 4a64628fb..c4211a971 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescaleset.py @@ -334,6 +334,7 @@ options: choices: - Flexible - Uniform + default: Flexible security_profile: description: - Specifies the Security related profile settings for the virtual machine sclaset. @@ -646,6 +647,7 @@ azure_vmss: ''' # NOQA import base64 +import time try: from azure.core.exceptions import ResourceNotFoundError @@ -723,7 +725,9 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): scale_in_policy=dict(type='str', choices=['Default', 'OldestVM', 'NewestVM']), terminate_event_timeout_minutes=dict(type='int'), ephemeral_os_disk=dict(type='bool'), - orchestration_mode=dict(type='str', choices=['Uniform', 'Flexible']), + orchestration_mode=dict(type='str', + choices=['Uniform', 'Flexible'], + default='Flexible',), platform_fault_domain_count=dict(type='int', default=1), os_disk_size_gb=dict(type='int'), security_profile=dict( @@ -1375,7 +1379,18 @@ class AzureRMVirtualMachineScaleSet(AzureRMModuleBase): :return: VirtualMachineScaleSet object ''' try: + retry_count = 0 vmss = self.compute_client.virtual_machine_scale_sets.get(self.resource_group, self.name) + while True: + if retry_count == 20: + self.fail("Error {0} has a provisioning state of Updating. Expecting state to be Successed.".format(self.name)) + + if vmss.provisioning_state != 'Succeeded': + retry_count = retry_count + 1 + time.sleep(150) + vmss = self.compute_client.virtual_machine_scale_sets.get(self.resource_group, self.name) + else: + break return vmss except ResourceNotFoundError as exc: self.fail("Error getting virtual machine scale set {0} - {1}".format(self.name, str(exc))) diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance.py index ca20000a8..402af0072 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance.py @@ -165,7 +165,6 @@ class AzureRMVirtualMachineScaleSetInstance(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(ComputeManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2021-04-01') instances = self.get() diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py index 07b6cf92c..47a3d3318 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualmachinescalesetinstance_info.py @@ -169,7 +169,6 @@ class AzureRMVirtualMachineScaleSetVMInfo(AzureRMModuleBase): setattr(self, key, kwargs[key]) self.mgmt_client = self.get_mgmt_svc_client(ComputeManagementClient, base_url=self._cloud_environment.endpoints.resource_manager, - is_track2=True, api_version='2021-04-01') if (self.instance_id is None): diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan.py index 38c542695..53bef71eb 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_virtualwan.py @@ -229,7 +229,7 @@ except ImportError: class Actions: - NoAction, Create, Update, Delete = range(4) + NoAction, Create, Update, Update_tags, Delete = range(5) class AzureRMVirtualWan(AzureRMModuleBaseExt): @@ -251,45 +251,34 @@ class AzureRMVirtualWan(AzureRMModuleBaseExt): required=True ), disable_vpn_encryption=dict( - type='bool', - disposition='/disable_vpn_encryption' + type='bool' ), virtual_hubs=dict( type='list', elements='dict', - updatable=False, - disposition='/virtual_hubs', options=dict( id=dict( - type='str', - disposition='id' + type='str' ) ) ), vpn_sites=dict( type='list', elements='dict', - updatable=False, - disposition='/vpn_sites', options=dict( id=dict( - type='str', - disposition='id' + type='str' ) ) ), allow_branch_to_branch_traffic=dict( - type='bool', - disposition='/allow_branch_to_branch_traffic' + type='bool' ), allow_vnet_to_vnet_traffic=dict( - type='bool', - updatable=False, - disposition='/allow_vnet_to_vnet_traffic' + type='bool' ), virtual_wan_type=dict( type='str', - disposition='/virtual_wan_type', choices=['Basic', 'Standard'] ), state=dict( @@ -313,14 +302,12 @@ class AzureRMVirtualWan(AzureRMModuleBaseExt): supports_tags=True) def exec_module(self, **kwargs): - for key in list(self.module_arg_spec.keys()): + for key in list(self.module_arg_spec.keys()) + ['tags']: if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: self.body[key] = kwargs[key] - self.inflate_parameters(self.module_arg_spec, self.body, 0) - resource_group = self.get_resource_group(self.resource_group) if self.location is None: # Set default location @@ -339,18 +326,28 @@ class AzureRMVirtualWan(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): - self.to_do = Actions.Update + compare_list = ['disable_vpn_encryption', 'allow_branch_to_branch_traffic'] + for key in compare_list: + if self.body.get(key) is not None and self.body[key] != old_response[key]: + self.log('parameter {0} does not match the configuration'.format(key)) + self.to_do = Actions.Update + else: + self.body[key] = old_response[key] + + update_tags, self.tags = self.update_tags(old_response.get('tags')) + if update_tags: + self.to_do = Actions.Update_tags if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): self.results['changed'] = True if self.check_mode: return self.results response = self.create_update_resource() + elif self.to_do == Actions.Update_tags: + self.results['changed'] = True + if self.check_mode: + return self.results + response = self.update_resource_tags(dict(tags=self.tags)) elif self.to_do == Actions.Delete: self.results['changed'] = True if self.check_mode: @@ -363,6 +360,18 @@ class AzureRMVirtualWan(AzureRMModuleBaseExt): self.results['state'] = response return self.results + def update_resource_tags(self, tags_parameters): + try: + response = self.network_client.virtual_wans.update_tags(resource_group_name=self.resource_group, + virtual_wan_name=self.name, + wan_parameters=tags_parameters) + if isinstance(response, LROPoller): + response = self.get_poller_result(response) + except Exception as exc: + self.log('Error attempting to Update the VirtualWan instance.') + self.fail('Error Updating the VirtualWan instance tags: {0}'.format(str(exc))) + return response.as_dict() + def create_update_resource(self): try: response = self.network_client.virtual_wans.begin_create_or_update(resource_group_name=self.resource_group, diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy.py index 5cd10c978..d3584b670 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy.py @@ -366,7 +366,6 @@ class VMBackupPolicy(AzureRMModuleBaseExt): response = None self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) old_response = self.get_resource() @@ -403,10 +402,12 @@ class VMBackupPolicy(AzureRMModuleBaseExt): self.log('Error in creating Backup Policy.') self.fail('Error in creating Backup Policy {0}'.format(str(e))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy_info.py index 0aa7b5918..0efe1df6c 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vmbackuppolicy_info.py @@ -216,7 +216,6 @@ class BackupPolicyVMInfo(AzureRMModuleBaseExt): self.url = self.get_url() self.mgmt_client = self.get_mgmt_svc_client(GenericRestClient, - is_track2=True, base_url=self._cloud_environment.endpoints.resource_manager) response = self.get_resource() @@ -243,10 +242,12 @@ class BackupPolicyVMInfo(AzureRMModuleBaseExt): except Exception as e: self.log('Backup policy does not exist.') self.fail('Error in fetching VM Backup Policy {0}'.format(str(e))) - try: + if hasattr(response, 'body'): response = json.loads(response.body()) - except Exception: - response = {'text': response.context['deserialized_data']} + elif hasattr(response, 'context'): + response = response.context['deserialized_data'] + else: + self.fail("Create or Updating fail, no match message return, return info as {0}".format(response)) return response diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite.py index 32d4fafee..c1b7ff8f8 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_vpnsite.py @@ -307,7 +307,7 @@ except ImportError: class Actions: - NoAction, Create, Update, Delete = range(4) + NoAction, Create, Update, Delete, Update_tags = range(5) class AzureRMVpnSite(AzureRMModuleBaseExt): @@ -326,92 +326,71 @@ class AzureRMVpnSite(AzureRMModuleBaseExt): ), virtual_wan=dict( type='dict', - disposition='/virtual_wan', options=dict( id=dict( type='str', - disposition='id' ) ) ), device_properties=dict( type='dict', - disposition='/device_properties', options=dict( device_vendor=dict( type='str', - disposition='device_vendor' ), device_model=dict( type='str', - disposition='device_model' ), link_speed_in_mbps=dict( type='int', - disposition='link_speed_in_mbps' ) ) ), ip_address=dict( type='str', - disposition='/ip_address' ), site_key=dict( type='str', no_log=True, - disposition='/site_key' ), address_space=dict( type='dict', - disposition='/address_space', options=dict( address_prefixes=dict( type='list', - disposition='address_prefixes', elements='str' ) ) ), bgp_properties=dict( type='dict', - disposition='/bgp_properties', options=dict( asn=dict( type='int', - disposition='asn' ), bgp_peering_address=dict( type='str', - disposition='bgp_peering_address' ), peer_weight=dict( type='int', - disposition='peer_weight' ), bgp_peering_addresses=dict( type='list', - disposition='bgp_peering_addresses', elements='dict', options=dict( ipconfiguration_id=dict( type='str', - disposition='ipconfiguration_id' ), default_bgp_ip_addresses=dict( type='list', - updatable=False, - disposition='default_bgp_ip_addresses', elements='str' ), custom_bgp_ip_addresses=dict( type='list', - disposition='custom_bgp_ip_addresses', elements='str' ), tunnel_ip_addresses=dict( type='list', - updatable=False, - disposition='tunnel_ip_addresses', elements='str' ) ) @@ -420,50 +399,39 @@ class AzureRMVpnSite(AzureRMModuleBaseExt): ), is_security_site=dict( type='bool', - disposition='/is_security_site' ), vpn_site_links=dict( type='list', - disposition='/vpn_site_links', elements='dict', options=dict( name=dict( type='str', - disposition='name' ), link_properties=dict( type='dict', - disposition='link_properties', options=dict( link_provider_name=dict( type='str', - disposition='link_provider_name' ), link_speed_in_mbps=dict( type='int', - disposition='link_speed_in_mbps' ) ) ), ip_address=dict( type='str', - disposition='ip_address' ), fqdn=dict( type='str', - disposition='fqdn' ), bgp_properties=dict( type='dict', - disposition='bgp_properties', options=dict( asn=dict( type='int', - disposition='asn' ), bgp_peering_address=dict( type='str', - disposition='bgp_peering_address' ) ) ) @@ -471,23 +439,18 @@ class AzureRMVpnSite(AzureRMModuleBaseExt): ), o365_policy=dict( type='dict', - disposition='/o365_policy', options=dict( break_out_categories=dict( type='dict', - disposition='break_out_categories', options=dict( allow=dict( type='bool', - disposition='allow' ), optimize=dict( type='bool', - disposition='optimize' ), default=dict( type='bool', - disposition='default' ) ) ) @@ -514,7 +477,7 @@ class AzureRMVpnSite(AzureRMModuleBaseExt): supports_tags=True) def exec_module(self, **kwargs): - for key in list(self.module_arg_spec.keys()): + for key in list(self.module_arg_spec.keys()) + ['tags']: if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: @@ -540,18 +503,62 @@ class AzureRMVpnSite(AzureRMModuleBaseExt): if self.state == 'absent': self.to_do = Actions.Delete else: - modifiers = {} - self.create_compare_modifiers(self.module_arg_spec, '', modifiers) - self.results['modifiers'] = modifiers - self.results['compare'] = [] - if not self.default_compare(modifiers, self.body, old_response, '', self.results): + if self.body.get('virtual_wan') is not None and self.body['virtual_wan'] != old_response.get('virtual_wan'): self.to_do = Actions.Update + for key in self.body.keys(): + if key == 'address_space': + if old_response.get('address_space') is None or\ + len(self.body['address_space']['address_prefixes']) > len(old_response['address_space']['address_prefixes']) or\ + not all(key in old_response['address_space']['address_prefixes'] for key in self.body['address_space']['address_prefixes']): + self.to_do = Actions.Update + elif key == 'device_properties': + if old_response.get('device_properties') is None or\ + not all(self.body['device_properties'][key] == old_response['device_properties'].get(key) + for key in self.body['device_properties'].keys()): + self.to_do = Actions.Update + elif key == 'o365_policy': + if old_response.get('o365_policy') is None or\ + not all(self.body['o365_policy']['break_out_categories'][key] == old_response['o365_policy']['break_out_categories'].get(key) + for key in self.body['o365_policy']['break_out_categories'].keys()): + self.to_do = Actions.Update + elif key == 'vpn_site_links': + if old_response.get('vpn_site_links') is None or\ + not all(self.body['vpn_site_links'][key] == old_response['vpn_site_links'].get(key) + for key in self.body['vpn_site_links'].keys()): + self.to_do = Actions.Update + elif key == 'bgp_properties': + if old_response.get('bgp_properties') is None: + self.to_do = Actions.Update + else: + for item in self.body['bgp_properties'].keys(): + if item != 'bgp_peering_addresses' and item != 'peer_weight': + if self.body['bgp_properties'][item] != old_response['bgp_properties'].get(item): + self.to_do = Actions.Update + else: + if self.body['bgp_properties'].get('bgp_peering_addresses') is not None: + bgp_address = old_response['bgp_properties']['bgp_peering_addresses'] + if old_response['bgp_properties'].get('bgp_peering_addresses') is None or\ + not all(self.body['bgp_properties']['bgp_peering_addresses'][value] == bgp_address.get(value) + for value in ['ipconfiguration_id', 'custom_bgp_ip_addresses']): + self.to_do = Actions.Update + + elif self.body[key] != old_response.get(key): + self.to_do = Actions.Update + + update_tags, self.tags = self.update_tags(old_response.get('tags')) + if update_tags: + self.to_do = Actions.Update_tags if (self.to_do == Actions.Create) or (self.to_do == Actions.Update): self.results['changed'] = True if self.check_mode: return self.results response = self.create_update_resource() + elif self.to_do == Actions.Update_tags: + self.results['changed'] = True + if self.check_mode: + return self.results + response = self.update_resource_tags(dict(tags=self.tags)) elif self.to_do == Actions.Delete: self.results['changed'] = True if self.check_mode: @@ -565,6 +572,18 @@ class AzureRMVpnSite(AzureRMModuleBaseExt): self.results['state'] = response return self.results + def update_resource_tags(self, tags_parameters): + try: + response = self.network_client.vpn_sites.update_tags(resource_group_name=self.resource_group, + vpn_site_name=self.name, + vpn_site_parameters=tags_parameters) + if isinstance(response, LROPoller): + response = self.get_poller_result(response) + except Exception as exc: + self.log('Error attempting to update the VpnSite instance tags.') + self.fail('Error updating the VpnSite instance: {0}'.format(str(exc))) + return response.as_dict() + def create_update_resource(self): try: response = self.network_client.vpn_sites.begin_create_or_update(resource_group_name=self.resource_group, diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp.py index 05697176b..e58cbcd43 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp.py @@ -76,13 +76,13 @@ options: version: description: - Version of the framework. For Linux web app supported value, see U(https://aka.ms/linux-stacks) for more info. - - C(net_framework) supported value sample, C(v4.0) for .NET 4.6 and C(v3.0) for .NET 3.5. - - C(php) supported value sample, C(5.5), C(5.6), C(7.0). - - C(python) supported value sample, C(2.7), C(3.8), C(3.10). - - C(node) supported value sample, C(6.6), C(6.9). - - C(dotnetcore) supported value sample, C(1.0), C(1.1), C(1.2). + - C(net_framework) supported value sample, C(v4.8) for .NET 4.8 and C(v3.5) for .NET 3.5. + - C(php) supported value sample, C(8.1), C(8.2). + - C(python) supported value sample, C(3.8), C(3.9), C(3.10), C(3.11), C(3.12). + - C(node) supported value sample, C(18), C(20). + - C(dotnetcore) supported value sample, C(8), C(7), C(6). - C(ruby) supported value sample, C(2.3). - - C(java) supported value sample, C(1.9) for Windows web app. C(1.8) for Linux web app. + - C(java) supported value sample, C(21), C(17), C(11) and C(8). type: str required: true settings: @@ -93,14 +93,14 @@ options: java_container: description: - Name of Java container. - - Supported only when I(frameworks=java). Sample values C(Tomcat), C(Jetty). + - Supported only when I(frameworks=java). Sample values C(Tomcat), C(JavaSE), C(RedHat). type: str required: True java_container_version: description: - Version of Java container. - Supported only when I(frameworks=java). - - Sample values for C(Tomcat), C(8.0), C(8.5), C(9.0). For C(Jetty,), C(9.1), C(9.3). + - Sample values for C(Tomcat), C(8.5), C(9.0), C(10.0), C(10.1). type: str required: True @@ -139,6 +139,11 @@ options: - Keeps the app loaded even when there's no traffic. type: bool + http20_enabled: + description: + - Configures a web site to allow clients to connect over HTTP 2.0. + type: bool + min_tls_version: description: - The minimum TLS encryption version required for the app. @@ -289,7 +294,7 @@ EXAMPLES = ''' testkey: testvalue frameworks: - name: "node" - version: "6.6" + version: "18" - name: Create a windows web app with node, php azure_rm_webapp: @@ -302,9 +307,9 @@ EXAMPLES = ''' testkey: testvalue frameworks: - name: "node" - version: 6.6 + version: 18 - name: "php" - version: "7.0" + version: 8.2 - name: Create a stage deployment slot for an existing web app azure_rm_webapp: @@ -494,6 +499,9 @@ class AzureRMWebApps(AzureRMModuleBase): always_on=dict( type='bool', ), + http20_enabled=dict( + type='bool', + ), min_tls_version=dict( type='str', choices=['1.0', '1.1', '1.2'], @@ -583,6 +591,7 @@ class AzureRMWebApps(AzureRMModuleBase): "python_version", "scm_type", "always_on", + "http20_enabled", "min_tls_version", "ftps_state"] @@ -591,7 +600,7 @@ class AzureRMWebApps(AzureRMModuleBase): "https_only"] self.supported_linux_frameworks = ['ruby', 'php', 'python', 'dotnetcore', 'node', 'java'] - self.supported_windows_frameworks = ['net_framework', 'php', 'python', 'node', 'java'] + self.supported_windows_frameworks = ['net_framework', 'php', 'python', 'node', 'java', 'dotnetcore'] super(AzureRMWebApps, self).__init__(derived_arg_spec=self.module_arg_spec, mutually_exclusive=mutually_exclusive, @@ -605,7 +614,7 @@ class AzureRMWebApps(AzureRMModuleBase): if hasattr(self, key): setattr(self, key, kwargs[key]) elif kwargs[key] is not None: - if key in ["scm_type", "always_on", "min_tls_version", "ftps_state"]: + if key in ["scm_type", "always_on", "http20_enabled", "min_tls_version", "ftps_state"]: self.site_config[key] = kwargs[key] old_response = None @@ -655,15 +664,15 @@ class AzureRMWebApps(AzureRMModuleBase): self.site_config['linux_fx_version'] = (self.frameworks[0]['name'] + '|' + self.frameworks[0]['version']).upper() if self.frameworks[0]['name'] == 'java': - if self.frameworks[0]['version'] != '8': - self.fail("Linux web app only supports java 8.") + if self.frameworks[0]['version'] not in ['8', '11', '17', '21']: + self.fail("Linux web app only supports java 8, 11, 17 and 21.") if self.frameworks[0]['settings'] and self.frameworks[0]['settings']['java_container'].lower() != 'tomcat': self.fail("Linux web app only supports tomcat container.") if self.frameworks[0]['settings'] and self.frameworks[0]['settings']['java_container'].lower() == 'tomcat': self.site_config['linux_fx_version'] = 'TOMCAT|' + self.frameworks[0]['settings']['java_container_version'] + '-jre8' else: - self.site_config['linux_fx_version'] = 'JAVA|8-jre8' + self.site_config['linux_fx_version'] = 'JAVA|{0}-jre{0}'.format(self.frameworks[0]['version']) else: for fx in self.frameworks: if fx.get('name') not in self.supported_windows_frameworks: @@ -852,7 +861,7 @@ class AzureRMWebApps(AzureRMModuleBase): # compare xxx_version def is_site_config_changed(self, existing_config): for updatable_property in self.site_config_updatable_properties: - if self.site_config.get(updatable_property): + if updatable_property in self.site_config: if not getattr(existing_config, updatable_property) or \ str(getattr(existing_config, updatable_property)).upper() != str(self.site_config.get(updatable_property)).upper(): return True diff --git a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp_info.py b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp_info.py index af035b152..c0ec6b42d 100644 --- a/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp_info.py +++ b/ansible_collections/azure/azcollection/plugins/modules/azure_rm_webapp_info.py @@ -138,6 +138,12 @@ webapps: returned: always type: bool sample: true + http20_enabled: + description: + - Configures a web site to allow clients to connect over HTTP 2.0. + returned: always + type: bool + sample: true min_tls_version: description: - The minimum TLS encryption version required for the app. @@ -486,6 +492,7 @@ class AzureRMWebAppInfo(AzureRMModuleBase): curated_output['frameworks'].append({'name': tmp[0].lower(), 'version': tmp[1]}) curated_output['always_on'] = configuration.get('always_on') + curated_output['http20_enabled'] = configuration.get('http20_enabled') curated_output['ftps_state'] = configuration.get('ftps_state') curated_output['min_tls_version'] = configuration.get('min_tls_version') diff --git a/ansible_collections/azure/azcollection/pr-pipelines.yml b/ansible_collections/azure/azcollection/pr-pipelines.yml index 6f40e066a..7ddcc40dc 100644 --- a/ansible_collections/azure/azcollection/pr-pipelines.yml +++ b/ansible_collections/azure/azcollection/pr-pipelines.yml @@ -19,9 +19,10 @@ parameters: - "2.10" - "2.11" - "2.12" - - "2.13" + - "2.13" # Eol Nov.6 2023 https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html - "2.14" - "2.15" + - "2.16" - "devel" - name: MODULE_NAME displayName: 'Test Module' @@ -85,6 +86,7 @@ parameters: - "azure_rm_notificationhub" - "azure_rm_openshiftmanagedcluster" - "azure_rm_postgresqlserver" + - "azure_rm_postgresqlflexibleserver" - "azure_rm_privatednsrecordset" - "azure_rm_privatednszone" - "azure_rm_privateendpoint" @@ -92,6 +94,7 @@ parameters: - "azure_rm_privatelinkservice" - "azure_rm_privatednszonelink" - "azure_rm_publicipaddress" + - "azure_rm_publicipprefix" - "azure_rm_proximityplacementgroup" - "azure_rm_rediscache" - "azure_rm_resource" @@ -135,6 +138,7 @@ parameters: - "azure_rm_devtestlab" - "azure_rm_sqlmanagedinstance" - "azure_rm_vmssnetworkinterface_info" + - "azure_rm_sshpublickey" - "inventory_azure" - "setup_azure" @@ -169,7 +173,7 @@ jobs: - job: RunTests dependsOn: CreateResourceGroups - timeoutInMinutes: 120 + timeoutInMinutes: 180 variables: TEST_RESOURCE_GROUP: $[ dependencies.CreateResourceGroups.outputs['setvar.resource_group'] ] TEST_RESOURCE_GROUP_SECONDARY: $[ dependencies.CreateResourceGroups.outputs['setvar.resource_group_secondary'] ] diff --git a/ansible_collections/azure/azcollection/requirements-azure.txt b/ansible_collections/azure/azcollection/requirements-azure.txt index 4aae3275d..5fc0064aa 100644 --- a/ansible_collections/azure/azcollection/requirements-azure.txt +++ b/ansible_collections/azure/azcollection/requirements-azure.txt @@ -1,10 +1,10 @@ packaging requests[security] xmltodict -msal==1.23.0 +msgraph-sdk==1.0.0 azure-cli-core==2.34.0 azure-common==1.1.11 -azure-identity==1.7.0 +azure-identity==1.14.0 azure-mgmt-authorization==2.0.0 azure-mgmt-apimanagement==3.0.0 azure-mgmt-batch==16.2.0 @@ -36,12 +36,9 @@ azure-mgmt-trafficmanager==1.0.0b1 azure-mgmt-web==6.1.0 azure-nspkg==2.0.0 azure-storage-blob==12.11.0 -msrest==0.7.1 azure-core==1.28.0 -msrestazure==0.6.4 azure-keyvault==4.2.0 azure-mgmt-keyvault==10.0.0 -azure-graphrbac==0.61.1 azure-mgmt-cosmosdb==6.4.0 azure-mgmt-hdinsight==9.0.0 azure-mgmt-devtestlabs==9.0.0 diff --git a/ansible_collections/azure/azcollection/sanity-requirements-azure.txt b/ansible_collections/azure/azcollection/sanity-requirements-azure.txt index e18c13718..65bf3ad16 100644 --- a/ansible_collections/azure/azcollection/sanity-requirements-azure.txt +++ b/ansible_collections/azure/azcollection/sanity-requirements-azure.txt @@ -1,5 +1,5 @@ voluptuous==0.13.1 pycodestyle==2.8.0 yamllint==1.26.3 -cryptography==41.0.4 +cryptography==42.0.4 pylint==2.13.5 diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_accesstoken_info/aliases b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_accesstoken_info/aliases new file mode 100644 index 000000000..3c63edec5 --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_accesstoken_info/aliases @@ -0,0 +1,3 @@ +cloud/azure +shippable/azure/group15 +destructive diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_accesstoken_info/meta/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_accesstoken_info/meta/main.yml new file mode 100644 index 000000000..95e1952f9 --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_accesstoken_info/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_azure diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_accesstoken_info/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_accesstoken_info/tasks/main.yml new file mode 100644 index 000000000..dbe625871 --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_accesstoken_info/tasks/main.yml @@ -0,0 +1,13 @@ +- name: Get access token for graphql + azure.azcollection.azure_rm_accesstoken_info: + scopes: + - https://graph.microsoft.com/.default + register: result + +- name: Assert the facts + ansible.builtin.assert: + that: + - result is not changed + - result is not failed + - "'access_token' in result" + - "'expires_on' in result" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adapplication/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adapplication/tasks/main.yml index 99813a48d..d19e0b8cd 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adapplication/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adapplication/tasks/main.yml @@ -1,12 +1,10 @@ - name: Set variables ansible.builtin.set_fact: - tenant_id: "{{ azure_tenant }}" display_name: "app{{ resource_group | hash('sha1') | truncate(20, True, '') }}" run_once: true - name: Create application azure_rm_adapplication: - tenant: "{{ tenant_id }}" display_name: "{{ display_name }}" register: create_output @@ -16,7 +14,6 @@ - name: Create application again idempotent test azure_rm_adapplication: - tenant: "{{ tenant_id }}" app_id: "{{ create_output.app_id }}" register: output @@ -26,9 +23,8 @@ - name: Create application with more parameter azure_rm_adapplication: - tenant: "{{ tenant_id }}" display_name: "{{ display_name }}-01" - available_to_other_tenants: false + sign_in_audience: AzureADandPersonalMicrosoftAccount credential_description: "for test" end_date: 2021-10-01 start_date: 2021-05-18 @@ -50,25 +46,29 @@ - name: Get ad app info by object id azure_rm_adapplication_info: object_id: "{{ create_output.object_id }}" - tenant: "{{ tenant_id }}" register: output - name: Get ad app info by app id azure_rm_adapplication_info: app_id: "{{ create_output.app_id }}" - tenant: "{{ tenant_id }}" register: output +- name: Get ad app info by display name + azure_rm_adapplication_info: + app_display_name: "{{ create_output.app_display_name }}" + register: display_name_test_output + - name: Assert the application facts ansible.builtin.assert: that: - output.applications[0].app_display_name == "{{ display_name }}" - output.applications | length == 1 + - display_name_test_output.applications[0].app_display_name == "{{ display_name }}" + - display_name_test_output.applications | length == 1 - name: Delete ad app by app id azure_rm_adapplication: app_id: "{{ create_output.app_id }}" - tenant: "{{ tenant_id }}" state: absent register: output @@ -79,7 +79,6 @@ - name: Delete ad app by app id azure_rm_adapplication: app_id: "{{ second_output.app_id }}" - tenant: "{{ tenant_id }}" state: absent register: output @@ -90,7 +89,6 @@ - name: Get ad app info by app id azure_rm_adapplication_info: app_id: "{{ create_output.app_id }}" - tenant: "{{ tenant_id }}" register: output - name: Assert there is no application diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adgroup/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adgroup/tasks/main.yml index b10580e65..9415c6ee3 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adgroup/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adgroup/tasks/main.yml @@ -1,6 +1,5 @@ - name: Set variables ansible.builtin.set_fact: - tenant_id: "{{ azure_tenant }}" resource_prefix: "{{ 999999999999999999994 | random | to_uuid }}" run_once: true @@ -8,24 +7,23 @@ azure_rm_adgroup_info: attribute_name: "displayName" attribute_value: "{{ resource_prefix }}-Group-Root" - tenant: "{{ tenant_id }}" register: get_nonexistent_group_display_name_shouldfail failed_when: - get_nonexistent_group_display_name_shouldfail.ad_groups != [] - name: Create Group Root azure_rm_adgroup: - tenant: "{{ tenant_id }}" display_name: "{{ resource_prefix }}-Group-Root" mail_nickname: "{{ resource_prefix }}-Group-Root" + description: 'for test' state: 'present' register: group_create_changed_shouldpass - name: Create Group Should Return Not Changed azure_rm_adgroup: - tenant: "{{ tenant_id }}" display_name: "{{ resource_prefix }}-Group-Root" mail_nickname: "{{ resource_prefix }}-Group-Root" + description: 'for test' state: 'present' register: group_create_unchanged_shouldpass @@ -43,17 +41,16 @@ - name: Return previously created group using object_id azure_rm_adgroup_info: object_id: "{{ group_create_unchanged_shouldpass.object_id }}" - tenant: "{{ tenant_id }}" register: get_created_object_id_shouldpass - name: Assert Returns are Equal to Created Group ansible.builtin.assert: that: - get_created_object_id_shouldpass.ad_groups[0].object_id == group_create_unchanged_shouldpass.object_id + - get_created_object_id_shouldpass.ad_groups[0].description == 'for test' - name: Create Group Member 1 azure_rm_adgroup: - tenant: "{{ tenant_id }}" display_name: "{{ resource_prefix }}-Group-Member-1" mail_nickname: "{{ resource_prefix }}-Group-Member-1" state: 'present' @@ -61,7 +58,6 @@ - name: Create Group Member 2 azure_rm_adgroup: - tenant: "{{ tenant_id }}" display_name: "{{ resource_prefix }}-Group-Member-2" mail_nickname: "{{ resource_prefix }}-Group-Member-2" state: 'present' @@ -69,13 +65,12 @@ - name: Ensure member is in group using display_name and mail_nickname azure_rm_adgroup: - tenant: "{{ tenant_id }}" display_name: "{{ resource_prefix }}-Group-Root" mail_nickname: "{{ resource_prefix }}-Group-Root" state: 'present' present_members: - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ create_pass_first.object_id }}" - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ create_pass_second.object_id }}" + - "{{ create_pass_first.object_id }}" + - "{{ create_pass_second.object_id }}" register: add_pass - name: Validate members are in the group @@ -86,11 +81,10 @@ - name: Ensure member is in group that is already present using object_id azure_rm_adgroup: - tenant: "{{ tenant_id }}" object_id: "{{ group_create_changed_shouldpass.object_id }}" state: 'present' present_members: - - "https://graph.windows.net/{{ tenant_id }}/directoryObjects/{{ create_pass_first.object_id }}" + - "{{ create_pass_first.object_id }}" register: add_already_present_member_to_group_shouldpass - name: Validate nothing changed from already present member @@ -100,7 +94,6 @@ - name: Ensure member is not in group using object_id azure_rm_adgroup: - tenant: "{{ tenant_id }}" object_id: "{{ group_create_changed_shouldpass.object_id }}" state: 'present' absent_members: @@ -115,7 +108,6 @@ - name: Ensure member is not in group that is already not in group using display_name and mail_nickname azure_rm_adgroup: - tenant: "{{ tenant_id }}" display_name: "{{ resource_prefix }}-Group-Root" mail_nickname: "{{ resource_prefix }}-Group-Root" state: 'present' @@ -131,14 +123,12 @@ - name: Return a specific group using object_id azure_rm_adgroup_info: object_id: "{{ group_create_changed_shouldpass.object_id }}" - tenant: "{{ tenant_id }}" register: object_id_shouldpass - name: Return a specific group using object_id and return_owners azure_rm_adgroup_info: object_id: "{{ group_create_changed_shouldpass.object_id }}" return_owners: true - tenant: "{{ tenant_id }}" register: object_id_return_owners_shouldpass - name: Return a specific group using object_id and return_owners and return_group_members @@ -146,41 +136,35 @@ object_id: "{{ group_create_changed_shouldpass.object_id }}" return_owners: true return_group_members: true - tenant: "{{ tenant_id }}" register: object_id_return_owners_and_group_members_shouldpass - name: Return a specific group using object_id and member_groups azure_rm_adgroup_info: object_id: "{{ group_create_changed_shouldpass.object_id }}" return_member_groups: true - tenant: "{{ tenant_id }}" register: object_id_return_member_groups_shouldpass - name: Return a specific group using object_id and check_membership azure_rm_adgroup_info: object_id: "{{ group_create_changed_shouldpass.object_id }}" check_membership: "{{ create_pass_first.object_id }}" - tenant: "{{ tenant_id }}" register: object_id_return_check_membership_shouldpass - name: Return a specific group using displayName attribute azure_rm_adgroup_info: attribute_name: "displayName" attribute_value: "{{ group_create_changed_shouldpass.display_name }}" - tenant: "{{ tenant_id }}" register: displayname_attribute_shouldpass - name: Return a specific group using mailNickname filter azure_rm_adgroup_info: odata_filter: "mailNickname eq '{{ group_create_changed_shouldpass.mail_nickname }}'" - tenant: "{{ tenant_id }}" register: mailnickname_filter_shouldpass - name: Return a different group using displayName attribute azure_rm_adgroup_info: attribute_name: "displayName" attribute_value: "{{ create_pass_second.display_name }}" - tenant: "{{ tenant_id }}" register: displayname_attribute_different_shouldpass - name: Assert All Returns Are Equal @@ -196,7 +180,6 @@ - name: Delete group Group Root on object_id azure_rm_adgroup: - tenant: "{{ tenant_id }}" object_id: "{{ group_create_unchanged_shouldpass.object_id }}" state: 'absent' register: group_delete_group_root_shouldpass @@ -204,14 +187,12 @@ - name: Try to return now deleted group Group Root using object_id azure_rm_adgroup_info: object_id: "{{ group_create_unchanged_shouldpass.object_id }}" - tenant: "{{ tenant_id }}" register: get_deleted_object_group_root_shouldfail failed_when: - - '"failed to get ad group info Resource" not in get_deleted_object_group_root_shouldfail.msg' + - '"does not exist or one of its queried" not in get_deleted_object_group_root_shouldfail.msg' - name: Delete group Group Member 1 on object_id azure_rm_adgroup: - tenant: "{{ tenant_id }}" object_id: "{{ create_pass_first.object_id }}" state: 'absent' register: group_delete_group_member_1_shouldpass @@ -219,14 +200,12 @@ - name: Try to return now deleted group Group Member 1 using object_id azure_rm_adgroup_info: object_id: "{{ create_pass_first.object_id }}" - tenant: "{{ tenant_id }}" register: get_deleted_object_group_member_1_shouldfail failed_when: - - '"failed to get ad group info Resource" not in get_deleted_object_group_member_1_shouldfail.msg' + - '"does not exist or one of its queried" not in get_deleted_object_group_member_1_shouldfail.msg' - name: Delete group Group Member 2 on object_id azure_rm_adgroup: - tenant: "{{ tenant_id }}" object_id: "{{ create_pass_second.object_id }}" state: 'absent' register: group_delete_group_member_2_shouldpass @@ -234,7 +213,6 @@ - name: Try to return now deleted group Group Member 2 using object_id azure_rm_adgroup_info: object_id: "{{ create_pass_second.object_id }}" - tenant: "{{ tenant_id }}" register: get_deleted_object_group_member_2_shouldfail failed_when: - - '"failed to get ad group info Resource" not in get_deleted_object_group_member_2_shouldfail.msg' + - '"does not exist or one of its queried" not in get_deleted_object_group_member_2_shouldfail.msg' diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adpassword/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adpassword/tasks/main.yml index f430af17f..60c78ea80 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adpassword/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adpassword/tasks/main.yml @@ -1,14 +1,11 @@ - name: Set variables ansible.builtin.set_fact: app_id: "e0a62513-1d81-480e-a6dc-5c99cdd58d9a" - tenant_id: "72f988bf-86f1-41af-91ab-2d7cd011db47" app_object_id: "b52e8275-a1ee-4c4a-86ff-15992e0920ed" - name: Create first ad password by app_id azure_rm_adpassword: app_id: "{{ app_id }}" - value: "Password@032900001" - tenant: "{{ tenant_id }}" state: present register: ad_fact @@ -19,8 +16,6 @@ - name: Create second ad password by app_object_id azure_rm_adpassword: - value: "Password@032900002" - tenant: "{{ tenant_id }}" app_object_id: "{{ app_object_id }}" state: present register: ad_fact02 @@ -33,12 +28,10 @@ - name: Create ad service principal azure_rm_adserviceprincipal: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" state: present - name: Get ad service principal info azure_rm_adserviceprincipal_info: - tenant: "{{ tenant_id }}" app_id: "{{ app_id }}" register: sp_info - name: Print Service principals facts @@ -47,8 +40,6 @@ - name: Create third ad password by service_principal_object_id azure_rm_adpassword: - value: "Password@032900003" - tenant: "{{ tenant_id }}" service_principal_object_id: "{{ sp_info.service_principals[0].object_id }}" state: present register: ad_fact03 @@ -61,8 +52,6 @@ - name: Can't update ad password azure_rm_adpassword: app_id: "{{ app_id }}" - value: "Password@032900003" - tenant: "{{ tenant_id }}" key_id: "{{ ad_fact.key_id }}" app_object_id: "{{ app_object_id }}" state: present @@ -72,7 +61,6 @@ - name: Get ad password info azure_rm_adpassword_info: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" key_id: "{{ ad_fact.key_id }}" app_object_id: "{{ app_object_id }}" register: ad_info @@ -87,7 +75,6 @@ azure_rm_adpassword: app_id: "{{ app_id }}" key_id: "{{ ad_fact.key_id }}" - tenant: "{{ tenant_id }}" app_object_id: "{{ app_object_id }}" state: absent register: output @@ -100,7 +87,6 @@ - name: Delete all ad password azure_rm_adpassword: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" app_object_id: "{{ app_object_id }}" state: absent register: output diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adserviceprincipal/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adserviceprincipal/tasks/main.yml index b138740d6..a861afb7b 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adserviceprincipal/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_adserviceprincipal/tasks/main.yml @@ -1,18 +1,15 @@ - name: Set variables ansible.builtin.set_fact: app_id: "e0a62513-1d81-480e-a6dc-5c99cdd58d9a" - tenant_id: "72f988bf-86f1-41af-91ab-2d7cd011db47" - name: Delete ad service principal azure_rm_adserviceprincipal: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" state: absent - name: Create ad service principal azure_rm_adserviceprincipal: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" state: present register: ad_fact @@ -24,7 +21,6 @@ - name: Create ad service principal (idempontent) azure_rm_adserviceprincipal: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" state: present register: output @@ -36,7 +32,6 @@ - name: Get ad service principal info by app_id azure_rm_adserviceprincipal_info: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" register: ad_info - name: Assert The ad service principals facts @@ -48,14 +43,12 @@ - name: Update ad service principal app_role_assignmentrequired to True azure_rm_adserviceprincipal: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" app_role_assignment_required: true state: present register: output - name: Get ad service principal info by object_id azure_rm_adserviceprincipal_info: - tenant: "{{ tenant_id }}" object_id: "{{ ad_info.service_principals[0].object_id }}" register: ad_info @@ -68,7 +61,6 @@ - name: Delete ad service principal azure_rm_adserviceprincipal: app_id: "{{ app_id }}" - tenant: "{{ tenant_id }}" state: absent register: output diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_aduser/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_aduser/tasks/main.yml index e3c9225e6..c02a263bb 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_aduser/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_aduser/tasks/main.yml @@ -1,6 +1,5 @@ - name: Prepare facts ansible.builtin.set_fact: - tenant_id: "{{ azure_tenant }}" user_id: "user{{ 999999999999999999994 | random | to_uuid }}@contoso.com" object_id: "{{ 999999999999999999994 | random | to_uuid }}" user_principal_name: "{{ 999999999999999999994 | random | to_uuid }}" @@ -9,7 +8,6 @@ - name: Create test user azure_rm_aduser: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" state: "present" account_enabled: true display_name: "Test_{{ user_principal_name }}_Display_Name" @@ -26,7 +24,6 @@ - name: Try to update existing user - idempotent check azure_rm_aduser: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" state: "present" display_name: "Test_{{ user_principal_name }}_Display_Name" mail_nickname: "Test_{{ user_principal_name }}_mail_nickname" @@ -43,7 +40,6 @@ - name: User_principal_name Should Pass azure_rm_aduser_info: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" register: get_user_should_pass - name: Assert user was created and account is enabled @@ -55,7 +51,6 @@ - name: Update test user azure_rm_aduser: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" state: "present" account_enabled: false register: update_user_should_pass @@ -63,7 +58,6 @@ - name: User_principal_name on updated user Should Pass azure_rm_aduser_info: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" register: get_updated_user_should_pass - name: Assert user was updated and account is disabled @@ -75,14 +69,12 @@ - name: Delete test user azure_rm_aduser: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" state: "absent" register: delete_user_should_pass - name: User_principal_name Should Fail azure_rm_aduser_info: user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" register: get_user_should_fail ignore_errors: true @@ -91,21 +83,8 @@ that: - "get_user_should_fail['failed'] == True" -- name: Run with bad tenant Should Fail - azure_rm_aduser_info: - user_principal_name: "{{ user_id }}" - tenant: None - register: missing_tenant - ignore_errors: true - -- name: Assert task failed - ansible.builtin.assert: - that: - - "missing_tenant['failed'] == True" - - name: Missing any identifiers Should Fail azure_rm_aduser_info: - tenant: "{{ tenant_id }}" register: missing_any_identifiers ignore_errors: true @@ -118,7 +97,6 @@ azure_rm_aduser_info: user_principal_name: "{{ user_id }}" object_id: "{{ object_id }}" - tenant: "{{ tenant_id }}" register: too_many_identifiers ignore_errors: true @@ -130,7 +108,6 @@ - name: Missing attribute_value Should Fail azure_rm_aduser_info: attribute_name: proxyAddresses - tenant: "{{ tenant_id }}" register: missing_attribute_value ignore_errors: true @@ -142,7 +119,6 @@ - name: Missing attribute_name Should Fail azure_rm_aduser_info: attribute_value: SMTP:user@contoso.com - tenant: "{{ tenant_id }}" register: missing_attribute_name ignore_errors: true @@ -155,7 +131,6 @@ azure_rm_aduser_info: all: true user_principal_name: "{{ user_id }}" - tenant: "{{ tenant_id }}" register: using_all_with_principal_name ignore_errors: true diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_aksagentpool/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_aksagentpool/tasks/main.yml index 26f71c211..7c255f9ad 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_aksagentpool/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_aksagentpool/tasks/main.yml @@ -33,6 +33,42 @@ outbound_type: loadBalancer register: output +- name: Get managecluster admin credentials + azure_rm_akscredentials_info: + resource_group: "{{ resource_group }}" + cluster_name: "min{{ rpfx }}" + show_admin_credentials: true + register: output + +- name: Verify that the cluster credentials are successfully obtained + ansible.builtin.assert: + that: + - output.cluster_credentials | length == 1 + +- name: Get managecluster user credentials + azure_rm_akscredentials_info: + resource_group: "{{ resource_group }}" + cluster_name: "min{{ rpfx }}" + show_user_credentials: true + register: output + +- name: Verify that the cluster credentials are successfully obtained + ansible.builtin.assert: + that: + - output.cluster_credentials | length == 1 + +- name: Get managecluster monitor user credentials + azure_rm_akscredentials_info: + resource_group: "{{ resource_group }}" + cluster_name: "min{{ rpfx }}" + show_monitor_credentials: true + register: output + +- name: Verify that the cluster credentials are successfully obtained + ansible.builtin.assert: + that: + - output.cluster_credentials | length == 1 + - name: Get cluster's node agent pool info azure_rm_aksagentpool_info: resource_group: "{{ resource_group }}" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_apimanagement/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_apimanagement/tasks/main.yml index d7d9b5fc5..2ca941b51 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_apimanagement/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_apimanagement/tasks/main.yml @@ -14,7 +14,7 @@ sku_name: Developer sku_capacity: 1 -- name: Pause for 60 mimutes to create api mangement +- name: Pause for 60 minutes to create api management ansible.builtin.pause: minutes: 60 changed_when: true diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_autoscale/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_autoscale/tasks/main.yml index 4a19ee340..a70411975 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_autoscale/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_autoscale/tasks/main.yml @@ -34,6 +34,7 @@ tier: Standard managed_disk_type: Standard_LRS os_disk_caching: ReadWrite + orchestration_mode: Uniform image: offer: 0001-com-ubuntu-server-focal publisher: Canonical diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_bastionhost/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_bastionhost/tasks/main.yml index e38f91eac..ac7340c4b 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_bastionhost/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_bastionhost/tasks/main.yml @@ -50,7 +50,7 @@ id: "{{ publicip_output.publicipaddresses[0].id }}" private_ip_allocation_method: Dynamic sku: - name: Standard + name: Basic enable_tunneling: false enable_shareable_link: false enable_ip_connect: false @@ -74,7 +74,7 @@ id: "{{ publicip_output.publicipaddresses[0].id }}" private_ip_allocation_method: Dynamic sku: - name: Standard + name: Basic enable_tunneling: false enable_shareable_link: false enable_ip_connect: false @@ -102,7 +102,7 @@ id: "{{ publicip_output.publicipaddresses[0].id }}" private_ip_allocation_method: Dynamic sku: - name: Standard + name: Basic enable_tunneling: false enable_shareable_link: false enable_ip_connect: false @@ -118,9 +118,9 @@ that: - not output.changed -- name: Pause for 20 mimutes to Bastion host updating +- name: Pause for 15 mimutes to Bastion host updating ansible.builtin.command: - sleep 1200 + sleep 900 changed_when: true - name: Update bastion host @@ -135,7 +135,7 @@ id: "{{ publicip_output.publicipaddresses[0].id }}" private_ip_allocation_method: Dynamic sku: - name: Basic + name: Standard enable_tunneling: true enable_shareable_link: true enable_ip_connect: true @@ -166,7 +166,12 @@ - output.bastion_host[0].enable_shareable_link == true - output.bastion_host[0].enable_tunneling == true - output.bastion_host[0].scale_units == 8 - - output.bastion_host[0].sku.name == 'Basic' + - output.bastion_host[0].sku.name == 'Standard' + +- name: Pause for 15 mimutes to Bastion host deleting + ansible.builtin.command: + sleep 900 + changed_when: true - name: Delete bastion host azure_rm_bastionhost: diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_cdnprofile/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_cdnprofile/tasks/main.yml index 92012c6f5..a537f1d8b 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_cdnprofile/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_cdnprofile/tasks/main.yml @@ -24,7 +24,8 @@ - name: Check there is no CDN profile created ansible.builtin.assert: - { that: "{{ fact.cdnprofiles | length }} == 0" } + that: + - fact.cdnprofiles | length == 0 - name: Create a CDN profile azure_rm_cdnprofile: diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_datalakestore/aliases b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_datalakestore/aliases index 5d29c6c4d..6feba04aa 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_datalakestore/aliases +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_datalakestore/aliases @@ -1,3 +1,4 @@ cloud/azure shippable/azure/group10 destructive +disabled diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_datalakestore/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_datalakestore/tasks/main.yml index c72dfc2ce..8dc08f8b7 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_datalakestore/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_datalakestore/tasks/main.yml @@ -71,7 +71,7 @@ - output.changed - output.state.virtual_network_rules | length == 1 - output.state.virtual_network_rules[0].name == "vnet_rule_1" - - output.state.virtual_network_rules[0].subnet_id == "{{ subnet_output.state.id }}" + - output.state.virtual_network_rules[0].subnet_id == subnet_output.state.id - name: Update data lake store to change encryption state that must fail azure_rm_datalakestore: @@ -154,7 +154,7 @@ - output.state.trusted_id_provider_state == "Disabled" - output.state.virtual_network_rules | length == 1 - output.state.virtual_network_rules[0].name == "vnet_rule_1" - - output.state.virtual_network_rules[0].subnet_id == "{{ subnet_output.state.id }}" + - output.state.virtual_network_rules[0].subnet_id == subnet_output.state.id - name: Create new data lake store (Idempotence) azure_rm_datalakestore: diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_diskencryptionset/lookup_plugins/azure_service_principal_attribute.py b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_diskencryptionset/lookup_plugins/azure_service_principal_attribute.py deleted file mode 100644 index c6f488f13..000000000 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_diskencryptionset/lookup_plugins/azure_service_principal_attribute.py +++ /dev/null @@ -1,92 +0,0 @@ -# (c) 2018 Yunge Zhu, <yungez@microsoft.com> -# (c) 2017 Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -DOCUMENTATION = """ -lookup: azure_service_principal_attribute - -requirements: - - azure-graphrbac - -author: - - Yunge Zhu <yungez@microsoft.com> - -version_added: "2.7" - -short_description: Look up Azure service principal attributes. - -description: - - Describes object id of your Azure service principal account. -options: - azure_client_id: - description: azure service principal client id. - azure_secret: - description: azure service principal secret - azure_tenant: - description: azure tenant - azure_cloud_environment: - description: azure cloud environment -""" - -EXAMPLES = """ -set_fact: - object_id: "{{ lookup('azure_service_principal_attribute', - azure_client_id=azure_client_id, - azure_secret=azure_secret, - azure_tenant=azure_secret) }}" -""" - -RETURN = """ -_raw: - description: - Returns object id of service principal. -""" - -from ansible.errors import AnsibleError -from ansible.plugins.lookup import LookupBase -from ansible.module_utils._text import to_native - -try: - from azure.common.credentials import ServicePrincipalCredentials - from azure.graphrbac import GraphRbacManagementClient - from azure.cli.core import cloud as azure_cloud -except ImportError: - raise AnsibleError( - "The lookup azure_service_principal_attribute requires azure.graphrbac, msrest") - - -class LookupModule(LookupBase): - def run(self, terms, variables, **kwargs): - - self.set_options(direct=kwargs) - - credentials = {} - credentials['azure_client_id'] = self.get_option('azure_client_id', None) - credentials['azure_secret'] = self.get_option('azure_secret', None) - credentials['azure_tenant'] = self.get_option('azure_tenant', 'common') - - if credentials['azure_client_id'] is None or credentials['azure_secret'] is None: - raise AnsibleError("Must specify azure_client_id and azure_secret") - - _cloud_environment = azure_cloud.AZURE_PUBLIC_CLOUD - if self.get_option('azure_cloud_environment', None) is not None: - cloud_environment = azure_cloud.get_cloud_from_metadata_endpoint(credentials['azure_cloud_environment']) - - try: - azure_credentials = ServicePrincipalCredentials(client_id=credentials['azure_client_id'], - secret=credentials['azure_secret'], - tenant=credentials['azure_tenant'], - resource=_cloud_environment.endpoints.active_directory_graph_resource_id) - - client = GraphRbacManagementClient(azure_credentials, credentials['azure_tenant'], - base_url=_cloud_environment.endpoints.active_directory_graph_resource_id) - - response = list(client.service_principals.list(filter="appId eq '{0}'".format(credentials['azure_client_id']))) - sp = response[0] - - return sp.object_id.split(',') - except Exception as ex: - raise AnsibleError("Failed to get service principal object id: %s" % to_native(ex)) - return False diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_diskencryptionset/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_diskencryptionset/tasks/main.yml index 0d805598e..ea767ed63 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_diskencryptionset/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_diskencryptionset/tasks/main.yml @@ -7,7 +7,7 @@ - name: Lookup service principal object id ansible.builtin.set_fact: - object_id: "{{ lookup('azure_service_principal_attribute', + object_id: "{{ lookup('azure.azcollection.azure_service_principal_attribute', azure_client_id=azure_client_id, azure_secret=azure_secret, azure_tenant=tenant_id) }}" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_gallery/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_gallery/tasks/main.yml index b9705dc34..8270b04ce 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_gallery/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_gallery/tasks/main.yml @@ -3,6 +3,64 @@ rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" run_once: true +- name: Lookup service principal object id + ansible.builtin.set_fact: + object_id: "{{ lookup('azure.azcollection.azure_service_principal_attribute', + azure_client_id=azure_client_id, + azure_secret=azure_secret, + azure_tenant=azure_tenant) }}" + register: object_id_facts + +- name: Create a key vault + azure_rm_keyvault: + resource_group: "{{ resource_group }}" + vault_name: "myvault{{ rpfx }}" + enabled_for_disk_encryption: true + vault_tenant: "{{ azure_tenant }}" + sku: + name: standard + family: A + access_policies: + - tenant_id: "{{ azure_tenant }}" + object_id: "{{ object_id }}" + keys: + - get + - list + - wrapkey + - unwrapkey + - create + - update + - import + - delete + - backup + - restore + - recover + - purge + +- name: Create a key in key vault + azure_rm_keyvaultkey: + key_name: testkey + keyvault_uri: https://myvault{{ rpfx }}.vault.azure.net + +- name: Get latest version of key + azure_rm_keyvaultkey_info: + vault_uri: https://myvault{{ rpfx }}.vault.azure.net + name: testkey + register: results + +- name: Assert the key vault facts + ansible.builtin.set_fact: + key_url: "{{ results['keys'][0]['kid'] }}" + +- name: Create disk encryption set + azure_rm_diskencryptionset: + resource_group: "{{ resource_group }}" + name: "des{{ rpfx }}" + source_vault: "myvault{{ rpfx }}" + key_url: "{{ key_url }}" + state: present + register: des_results + - name: Create virtual network azure_rm_virtualnetwork: resource_group: "{{ resource_group }}" @@ -53,11 +111,6 @@ name: "vmforimage{{ rpfx }}" register: output -- name: Pause for 10 mimutes to VM updating - ansible.builtin.command: - sleep 600 - changed_when: true - - name: Create a snapshot by importing an unmanaged blob from the same subscription. azure_rm_snapshot: resource_group: "{{ resource_group }}" @@ -151,7 +204,7 @@ name: myGallery{{ rpfx }} register: output -- name: Assedrt the gallery facts +- name: Assert the gallery facts ansible.builtin.assert: that: - not output.changed @@ -174,6 +227,10 @@ offer: myOfferName sku: mySkuName description: Image Description + hypervgeneration: V2 + features: + - name: SecurityType + value: TrustedLaunch register: output - name: Assert the gallery image created @@ -194,6 +251,10 @@ offer: myOfferName sku: mySkuName description: Image Description + hypervgeneration: V2 + features: + - name: SecurityType + value: TrustedLaunch register: output - name: Assert the gallery image idempotent result @@ -214,6 +275,10 @@ offer: myOfferName sku: mySkuName description: Image Description XXXs + hypervgeneration: V2 + features: + - name: SecurityType + value: TrustedLaunch register: output - name: Assert the gallery image updated @@ -254,10 +319,21 @@ target_regions: - name: eastus regional_replica_count: 1 + encryption: + data_disk_images: + - disk_encryption_set_id: "{{ des_results.state.id }}" + os_disk_image: + disk_encryption_set_id: "{{ des_results.state.id }}" - name: westus regional_replica_count: 2 + encryption: + data_disk_images: + - disk_encryption_set_id: "{{ des_results.state.id }}" + os_disk_image: + disk_encryption_set_id: "{{ des_results.state.id }}" storage_account_type: Standard_ZRS - managed_image: + storage_profile: + source_image: name: testimagea resource_group: "{{ resource_group }}" register: output @@ -282,10 +358,21 @@ target_regions: - name: eastus regional_replica_count: 1 + encryption: + data_disk_images: + - disk_encryption_set_id: "{{ des_results.state.id }}" + os_disk_image: + disk_encryption_set_id: "{{ des_results.state.id }}" - name: westus regional_replica_count: 2 + encryption: + data_disk_images: + - disk_encryption_set_id: "{{ des_results.state.id }}" + os_disk_image: + disk_encryption_set_id: "{{ des_results.state.id }}" storage_account_type: Standard_ZRS - managed_image: + storage_profile: + source_image: name: testimagea resource_group: "{{ resource_group }}" register: output @@ -310,10 +397,21 @@ target_regions: - name: eastus regional_replica_count: 1 + encryption: + data_disk_images: + - disk_encryption_set_id: "{{ des_results.state.id }}" + os_disk_image: + disk_encryption_set_id: "{{ des_results.state.id }}" - name: westus regional_replica_count: 2 + encryption: + data_disk_images: + - disk_encryption_set_id: "{{ des_results.state.id }}" + os_disk_image: + disk_encryption_set_id: "{{ des_results.state.id }}" storage_account_type: Standard_ZRS - managed_image: + storage_profile: + source_image: name: testimagea resource_group: "{{ resource_group }}" register: output diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvault/lookup_plugins/azure_service_principal_attribute.py b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvault/lookup_plugins/azure_service_principal_attribute.py deleted file mode 100644 index c6f488f13..000000000 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvault/lookup_plugins/azure_service_principal_attribute.py +++ /dev/null @@ -1,92 +0,0 @@ -# (c) 2018 Yunge Zhu, <yungez@microsoft.com> -# (c) 2017 Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -DOCUMENTATION = """ -lookup: azure_service_principal_attribute - -requirements: - - azure-graphrbac - -author: - - Yunge Zhu <yungez@microsoft.com> - -version_added: "2.7" - -short_description: Look up Azure service principal attributes. - -description: - - Describes object id of your Azure service principal account. -options: - azure_client_id: - description: azure service principal client id. - azure_secret: - description: azure service principal secret - azure_tenant: - description: azure tenant - azure_cloud_environment: - description: azure cloud environment -""" - -EXAMPLES = """ -set_fact: - object_id: "{{ lookup('azure_service_principal_attribute', - azure_client_id=azure_client_id, - azure_secret=azure_secret, - azure_tenant=azure_secret) }}" -""" - -RETURN = """ -_raw: - description: - Returns object id of service principal. -""" - -from ansible.errors import AnsibleError -from ansible.plugins.lookup import LookupBase -from ansible.module_utils._text import to_native - -try: - from azure.common.credentials import ServicePrincipalCredentials - from azure.graphrbac import GraphRbacManagementClient - from azure.cli.core import cloud as azure_cloud -except ImportError: - raise AnsibleError( - "The lookup azure_service_principal_attribute requires azure.graphrbac, msrest") - - -class LookupModule(LookupBase): - def run(self, terms, variables, **kwargs): - - self.set_options(direct=kwargs) - - credentials = {} - credentials['azure_client_id'] = self.get_option('azure_client_id', None) - credentials['azure_secret'] = self.get_option('azure_secret', None) - credentials['azure_tenant'] = self.get_option('azure_tenant', 'common') - - if credentials['azure_client_id'] is None or credentials['azure_secret'] is None: - raise AnsibleError("Must specify azure_client_id and azure_secret") - - _cloud_environment = azure_cloud.AZURE_PUBLIC_CLOUD - if self.get_option('azure_cloud_environment', None) is not None: - cloud_environment = azure_cloud.get_cloud_from_metadata_endpoint(credentials['azure_cloud_environment']) - - try: - azure_credentials = ServicePrincipalCredentials(client_id=credentials['azure_client_id'], - secret=credentials['azure_secret'], - tenant=credentials['azure_tenant'], - resource=_cloud_environment.endpoints.active_directory_graph_resource_id) - - client = GraphRbacManagementClient(azure_credentials, credentials['azure_tenant'], - base_url=_cloud_environment.endpoints.active_directory_graph_resource_id) - - response = list(client.service_principals.list(filter="appId eq '{0}'".format(credentials['azure_client_id']))) - sp = response[0] - - return sp.object_id.split(',') - except Exception as ex: - raise AnsibleError("Failed to get service principal object id: %s" % to_native(ex)) - return False diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvault/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvault/tasks/main.yml index 07f324d22..ef6b53a4d 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvault/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvault/tasks/main.yml @@ -6,7 +6,7 @@ - name: Lookup service principal object id ansible.builtin.set_fact: - object_id: "{{ lookup('azure_service_principal_attribute', + object_id: "{{ lookup('azure.azcollection.azure_service_principal_attribute', azure_client_id=azure_client_id, azure_secret=azure_secret, azure_tenant=tenant_id) }}" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultkey/lookup_plugins/azure_service_principal_attribute.py b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultkey/lookup_plugins/azure_service_principal_attribute.py deleted file mode 100644 index c6f488f13..000000000 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultkey/lookup_plugins/azure_service_principal_attribute.py +++ /dev/null @@ -1,92 +0,0 @@ -# (c) 2018 Yunge Zhu, <yungez@microsoft.com> -# (c) 2017 Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -DOCUMENTATION = """ -lookup: azure_service_principal_attribute - -requirements: - - azure-graphrbac - -author: - - Yunge Zhu <yungez@microsoft.com> - -version_added: "2.7" - -short_description: Look up Azure service principal attributes. - -description: - - Describes object id of your Azure service principal account. -options: - azure_client_id: - description: azure service principal client id. - azure_secret: - description: azure service principal secret - azure_tenant: - description: azure tenant - azure_cloud_environment: - description: azure cloud environment -""" - -EXAMPLES = """ -set_fact: - object_id: "{{ lookup('azure_service_principal_attribute', - azure_client_id=azure_client_id, - azure_secret=azure_secret, - azure_tenant=azure_secret) }}" -""" - -RETURN = """ -_raw: - description: - Returns object id of service principal. -""" - -from ansible.errors import AnsibleError -from ansible.plugins.lookup import LookupBase -from ansible.module_utils._text import to_native - -try: - from azure.common.credentials import ServicePrincipalCredentials - from azure.graphrbac import GraphRbacManagementClient - from azure.cli.core import cloud as azure_cloud -except ImportError: - raise AnsibleError( - "The lookup azure_service_principal_attribute requires azure.graphrbac, msrest") - - -class LookupModule(LookupBase): - def run(self, terms, variables, **kwargs): - - self.set_options(direct=kwargs) - - credentials = {} - credentials['azure_client_id'] = self.get_option('azure_client_id', None) - credentials['azure_secret'] = self.get_option('azure_secret', None) - credentials['azure_tenant'] = self.get_option('azure_tenant', 'common') - - if credentials['azure_client_id'] is None or credentials['azure_secret'] is None: - raise AnsibleError("Must specify azure_client_id and azure_secret") - - _cloud_environment = azure_cloud.AZURE_PUBLIC_CLOUD - if self.get_option('azure_cloud_environment', None) is not None: - cloud_environment = azure_cloud.get_cloud_from_metadata_endpoint(credentials['azure_cloud_environment']) - - try: - azure_credentials = ServicePrincipalCredentials(client_id=credentials['azure_client_id'], - secret=credentials['azure_secret'], - tenant=credentials['azure_tenant'], - resource=_cloud_environment.endpoints.active_directory_graph_resource_id) - - client = GraphRbacManagementClient(azure_credentials, credentials['azure_tenant'], - base_url=_cloud_environment.endpoints.active_directory_graph_resource_id) - - response = list(client.service_principals.list(filter="appId eq '{0}'".format(credentials['azure_client_id']))) - sp = response[0] - - return sp.object_id.split(',') - except Exception as ex: - raise AnsibleError("Failed to get service principal object id: %s" % to_native(ex)) - return False diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultkey/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultkey/tasks/main.yml index 869cb7257..4eb819546 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultkey/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultkey/tasks/main.yml @@ -6,7 +6,7 @@ - name: Lookup service principal object id ansible.builtin.set_fact: - object_id: "{{ lookup('azure_service_principal_attribute', + object_id: "{{ lookup('azure.azcollection.azure_service_principal_attribute', azure_client_id=azure_client_id, azure_secret=azure_secret, azure_tenant=tenant_id) }}" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultsecret/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultsecret/tasks/main.yml index d91641d80..cc228c2d7 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultsecret/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_keyvaultsecret/tasks/main.yml @@ -6,7 +6,7 @@ - name: Lookup service principal object id ansible.builtin.set_fact: - object_id: "{{ lookup('azure_service_principal_attribute', + object_id: "{{ lookup('azure.azcollection.azure_service_principal_attribute', azure_client_id=azure_client_id, azure_secret=azure_secret, azure_tenant=tenant_id) }}" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml index 969347b8d..3dd784e8a 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_openshiftmanagedcluster/tasks/main.yml @@ -114,6 +114,50 @@ ansible.builtin.assert: that: output['clusters'] | length >= 1 +- name: Fetch kubeconfig file to register + azure_rm_openshiftmanagedclusterkubeconfig_info: + name: "{{ cluster_name }}" + resource_group: "{{ resource_group }}" + register: kubeconfig_reg + +- name: Assert the kubeconfig file facts + ansible.builtin.assert: + that: kubeconfig_reg['kubeconfig'] | length >= 1 + +- name: Fetch kubeconfig file with specific name + azure_rm_openshiftmanagedclusterkubeconfig_info: + name: "{{ cluster_name }}" + resource_group: "{{ resource_group }}" + path: "/home/testuser/{{ cluster_name }}" + +- name: Check for created named kubeconfig file + ansible.builtin.stat: + path: "/home/testuser/{{ cluster_name }}" + register: named_kubeconf_file + +- name: Assert kubeconfig file creation with specific name + ansible.builtin.assert: + that: + - named_kubeconf_file.stat.exists + - named_kubeconf_file.stat.size != 0 + +- name: Fetch kubeconfig file with default name (kubeconfig) + azure_rm_openshiftmanagedclusterkubeconfig_info: + name: "{{ cluster_name }}" + resource_group: "{{ resource_group }}" + path: "/home/testuser/" + +- name: Check for created default kubeconfig file + ansible.builtin.stat: + path: "/home/testuser/kubeconfig" + register: default_kubeconf_file + +- name: Assert kubeconfig file creation with default name + ansible.builtin.assert: + that: + - default_kubeconf_file.stat.exists + - default_kubeconf_file.stat.size != 0 + - name: Delete openshift cluster azure_rm_openshiftmanagedcluster: resource_group: "{{ resource_group }}" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_postgresqlflexibleserver/aliases b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_postgresqlflexibleserver/aliases new file mode 100644 index 000000000..5d29c6c4d --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_postgresqlflexibleserver/aliases @@ -0,0 +1,3 @@ +cloud/azure +shippable/azure/group10 +destructive diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_postgresqlflexibleserver/meta/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_postgresqlflexibleserver/meta/main.yml new file mode 100644 index 000000000..95e1952f9 --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_postgresqlflexibleserver/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_azure diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_postgresqlflexibleserver/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_postgresqlflexibleserver/tasks/main.yml new file mode 100644 index 000000000..2add54e1e --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_postgresqlflexibleserver/tasks/main.yml @@ -0,0 +1,356 @@ +- name: Prepare random number + ansible.builtin.set_fact: + rpfx: "{{ resource_group | hash('md5') | truncate(8, True, '') }}" + new_resource_group: "{{ resource_group }}-02" + run_once: true + +- name: Create a new resource group + azure_rm_resourcegroup: + name: "{{ new_resource_group }}" + location: southeastasia + +- name: Create post gresql flexible server (check mode) + azure_rm_postgresqlflexibleserver: + resource_group: "{{ new_resource_group }}" + name: postflexible{{ rpfx }} + sku: + name: Standard_B1ms + tier: Burstable + administrator_login: azureuser + administrator_login_password: Fred@0329 + version: 12 + storage: + storage_size_gb: 128 + fully_qualified_domain_name: st-private-dns-zone.postgres.database.azure.com + backup: + backup_retention_days: 7 + geo_redundant_backup: Disabled + network: + public_network_access: Disabled + maintenance_window: + custom_window: Enabled + start_hour: 8 + start_minute: 4 + day_of_week: 3 + availability_zone: 2 + create_mode: Create + check_mode: true + +- name: Create post gresql flexible server + azure_rm_postgresqlflexibleserver: + resource_group: "{{ new_resource_group }}" + name: postflexible{{ rpfx }} + sku: + name: Standard_B1ms + tier: Burstable + administrator_login: azureuser + administrator_login_password: Fred@0329 + version: 12 + storage: + storage_size_gb: 128 + fully_qualified_domain_name: st-private-dns-zone.postgres.database.azure.com + backup: + backup_retention_days: 7 + geo_redundant_backup: Disabled + network: + public_network_access: Disabled + maintenance_window: + custom_window: Enabled + start_hour: 8 + start_minute: 4 + day_of_week: 3 + availability_zone: 2 + create_mode: Create + register: output + +- name: Assert the post grep sql server create success + ansible.builtin.assert: + that: + - output.changed + +- name: Create post gresql flexible server (Idempotent Test) + azure_rm_postgresqlflexibleserver: + resource_group: "{{ new_resource_group }}" + name: postflexible{{ rpfx }} + sku: + name: Standard_B1ms + tier: Burstable + administrator_login: azureuser + administrator_login_password: Fred@0329 + version: 12 + storage: + storage_size_gb: 128 + fully_qualified_domain_name: st-private-dns-zone.postgres.database.azure.com + backup: + backup_retention_days: 7 + geo_redundant_backup: Disabled + network: + public_network_access: Disabled + maintenance_window: + custom_window: Enabled + start_hour: 8 + start_minute: 4 + day_of_week: 3 + availability_zone: 2 + create_mode: Create + register: output + +- name: Assert the post grep sql server create success + ansible.builtin.assert: + that: + - not output.changed + +- name: Update post gresql flexible server with multiple parameters + azure_rm_postgresqlflexibleserver: + resource_group: "{{ new_resource_group }}" + name: postflexible{{ rpfx }} + sku: + name: Standard_B1ms + tier: Burstable + administrator_login: azureuser + administrator_login_password: Fred@0329 + version: 12 + storage: + storage_size_gb: 256 + fully_qualified_domain_name: st-private-dns-zone.postgres.database.azure.com + backup: + backup_retention_days: 7 + geo_redundant_backup: Disabled + network: + public_network_access: Disabled + maintenance_window: + custom_window: Enabled + start_hour: 10 + start_minute: 6 + day_of_week: 6 + availability_zone: 2 + create_mode: Create + tags: + key1: value1 + key2: value2 + register: output + +- name: Assert the post grep sql server update success + ansible.builtin.assert: + that: + - output.changed + +- name: Gather facts postgresql flexible Server + azure_rm_postgresqlflexibleserver_info: + resource_group: "{{ new_resource_group }}" + name: postflexible{{ rpfx }} + register: output + +- name: Assert the post gresql server is well created + ansible.builtin.assert: + that: + - output.servers[0].tags | length == 2 + - output.servers[0].storage.storage_size_gb == 256 + - output.servers[0].maintenance_window.custom_window == 'Enabled' + - output.servers[0].maintenance_window.day_of_week == 6 + - output.servers[0].maintenance_window.start_hour == 10 + - output.servers[0].maintenance_window.start_minute == 6 + +- name: Create a post gresql flexible database(check mode) + azure_rm_postgresqlflexibledatabase: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: database{{ rpfx }} + collation: en_US.utf8 + charset: UTF8 + check_mode: true + +- name: Create a post gresql flexible database + azure_rm_postgresqlflexibledatabase: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: database{{ rpfx }} + collation: en_US.utf8 + charset: UTF8 + register: output + +- name: Assert the post gresql flexible database created success + ansible.builtin.assert: + that: + - output.changed + +- name: Create a post gresql flexible database(Idempotent test) + azure_rm_postgresqlflexibledatabase: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: database{{ rpfx }} + collation: en_US.utf8 + charset: UTF8 + register: output + +- name: Assert the post gresql flexible database no changed + ansible.builtin.assert: + that: + - not output.changed + +- name: Get the post gresql flexibe database facts + azure_rm_postgresqlflexibledatabase_info: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: database{{ rpfx }} + register: output + +- name: Assert the post gresql flexible database facts + ansible.builtin.assert: + that: + - output.databases[0].collation == 'en_US.utf8' + - output.databases[0].charset == 'UTF8' + +- name: Delete the post gresql flexibe database + azure_rm_postgresqlflexibledatabase: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: database{{ rpfx }} + state: absent + register: output + +- name: Assert the post gresql flexible database deleted + ansible.builtin.assert: + that: + - output.changed + +- name: Create a post gresql flexible firwall rule (Check mode) + azure_rm_postgresqlflexiblefirewallrule: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: firewall{{ rpfx }} + start_ip_address: 10.0.0.15 + end_ip_address: 10.0.0.20 + check_mode: true + +- name: Create the post gresql flexible firwall rule + azure_rm_postgresqlflexiblefirewallrule: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: firewall{{ rpfx }} + start_ip_address: 10.0.0.15 + end_ip_address: 10.0.0.20 + register: output + +- name: Assert the post grepsql flexible firewall rule created well + ansible.builtin.assert: + that: + - output.changed + +- name: Create the post gresql flexible firwall rule (Idempotent test) + azure_rm_postgresqlflexiblefirewallrule: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: firewall{{ rpfx }} + start_ip_address: 10.0.0.15 + end_ip_address: 10.0.0.20 + register: output + +- name: Assert the post grepsql flexible firewall rule support idempotent test + ansible.builtin.assert: + that: + - not output.changed + +- name: Update the post gresql flexible firwall rule + azure_rm_postgresqlflexiblefirewallrule: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: firewall{{ rpfx }} + start_ip_address: 10.0.0.16 + end_ip_address: 10.0.0.18 + register: output + +- name: Assert the post grepsql flexible server update well + ansible.builtin.assert: + that: + - output.changed + +- name: Get the post gresql flexible firwall rule facts + azure_rm_postgresqlflexiblefirewallrule_info: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: firewall{{ rpfx }} + register: output + +- name: Assert the post gresql flexible firewall rule facts + ansible.builtin.assert: + that: + - output.firewall_rules[0].start_ip_address == '10.0.0.16' + - output.firewall_rules[0].end_ip_address == '10.0.0.18' + +- name: Delete the post gresql flexible firwall rule + azure_rm_postgresqlflexiblefirewallrule: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + name: firewall{{ rpfx }} + state: absent + register: output + +- name: Assert the post grepsql flexible server delete well + ansible.builtin.assert: + that: + - output.changed + +- name: List the post gresql flexible config facts + azure_rm_postgresqlflexibleconfiguration_info: + resource_group: "{{ new_resource_group }}" + server_name: postflexible{{ rpfx }} + register: output + +- name: Assert the post gresql flexible server configuration + ansible.builtin.assert: + that: + - output.settings | length > 0 + +- name: Stop the post gresql flexible server + azure_rm_postgresqlflexibleserver: + resource_group: "{{ new_resource_group }}" + name: postflexible{{ rpfx }} + is_stop: true + register: output + +- name: Assert the post grep sql server stop success + ansible.builtin.assert: + that: + - output.changed + +- name: Pause for 10 mimutes + ansible.builtin.pause: + minutes: 10 + changed_when: true + +- name: Restart post gresql flexible server + azure_rm_postgresqlflexibleserver: + resource_group: "{{ new_resource_group }}" + name: postflexible{{ rpfx }} + is_restart: true + register: output + +- name: Assert the post grep sql server restart success + ansible.builtin.assert: + that: + - output.changed + +- name: Delete post gresql flexible server + azure_rm_postgresqlflexibleserver: + resource_group: "{{ new_resource_group }}" + name: postflexible{{ rpfx }} + state: absent + register: output + +- name: Assert the post gresql server is well deleted + ansible.builtin.assert: + that: + - output.changed + +- name: Delete the new resource group + azure_rm_resourcegroup: + name: "{{ new_resource_group }}" + force_delete_nonempty: true + state: absent + register: output + +- name: Assert the resource group is well deleted + ansible.builtin.assert: + that: + - output.changed diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_privateendpointdnszonegroup/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_privateendpointdnszonegroup/tasks/main.yml index b5fc3e1f1..7b41ba31a 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_privateendpointdnszonegroup/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_privateendpointdnszonegroup/tasks/main.yml @@ -118,7 +118,7 @@ - output.state.private_dns_zone_configs[0].record_sets | length == 1 - output.state.private_dns_zone_configs[0].record_sets[0].fqdn == 'postgresqlsrv-{{ rpfx }}.privatelink.postgres.database.azure.com' - output.state.private_dns_zone_configs[0].record_sets[0].ip_addresses | length == 1 - - output.state.private_dns_zone_configs[0].record_sets[0].ip_addresses[0] is match('^10.1.*') + - output.state.private_dns_zone_configs[0].record_sets[0].ip_addresses[0] is match('10.1.*') - output.state.private_dns_zone_configs[0].record_sets[0].provisioning_state == 'Succeeded' - output.state.private_dns_zone_configs[0].record_sets[0].record_set_name == 'postgresqlsrv-{{ rpfx }}' - output.state.private_dns_zone_configs[0].record_sets[0].record_type == 'A' @@ -158,7 +158,7 @@ - output.groups[0].private_dns_zone_configs[0].record_sets | length == 1 - output.groups[0].private_dns_zone_configs[0].record_sets[0].fqdn == 'postgresqlsrv-{{ rpfx }}.privatelink.postgres.database.azure.com' - output.groups[0].private_dns_zone_configs[0].record_sets[0].ip_addresses | length == 1 - - output.groups[0].private_dns_zone_configs[0].record_sets[0].ip_addresses[0] is match('^10.1.*') + - output.groups[0].private_dns_zone_configs[0].record_sets[0].ip_addresses[0] is match('10.1.*') - output.groups[0].private_dns_zone_configs[0].record_sets[0].provisioning_state == 'Succeeded' - output.groups[0].private_dns_zone_configs[0].record_sets[0].record_set_name == 'postgresqlsrv-{{ rpfx }}' - output.groups[0].private_dns_zone_configs[0].record_sets[0].record_type == 'A' @@ -183,7 +183,7 @@ - output.groups[0].private_dns_zone_configs[0].record_sets | length == 1 - output.groups[0].private_dns_zone_configs[0].record_sets[0].fqdn == 'postgresqlsrv-{{ rpfx }}.privatelink.postgres.database.azure.com' - output.groups[0].private_dns_zone_configs[0].record_sets[0].ip_addresses | length == 1 - - output.groups[0].private_dns_zone_configs[0].record_sets[0].ip_addresses[0] is match('^10.1.*') + - output.groups[0].private_dns_zone_configs[0].record_sets[0].ip_addresses[0] is match('10.1.*') - output.groups[0].private_dns_zone_configs[0].record_sets[0].provisioning_state == 'Succeeded' - output.groups[0].private_dns_zone_configs[0].record_sets[0].record_set_name == 'postgresqlsrv-{{ rpfx }}' - output.groups[0].private_dns_zone_configs[0].record_sets[0].record_type == 'A' @@ -211,7 +211,7 @@ - output.state.private_dns_zone_configs[0].record_sets | length == 1 - output.state.private_dns_zone_configs[0].record_sets[0].fqdn == 'postgresqlsrv-{{ rpfx }}.privatelink.postgres.database.azure.com' - output.state.private_dns_zone_configs[0].record_sets[0].ip_addresses | length == 1 - - output.state.private_dns_zone_configs[0].record_sets[0].ip_addresses[0] is match('^10.1.*') + - output.state.private_dns_zone_configs[0].record_sets[0].ip_addresses[0] is match('10.1.*') - output.state.private_dns_zone_configs[0].record_sets[0].provisioning_state == 'Succeeded' - output.state.private_dns_zone_configs[0].record_sets[0].record_set_name == 'postgresqlsrv-{{ rpfx }}' - output.state.private_dns_zone_configs[0].record_sets[0].record_type == 'A' diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_publicipprefix/aliases b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_publicipprefix/aliases new file mode 100644 index 000000000..aa77c071a --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_publicipprefix/aliases @@ -0,0 +1,3 @@ +cloud/azure +shippable/azure/group2 +destructive diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_publicipprefix/meta/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_publicipprefix/meta/main.yml new file mode 100644 index 000000000..95e1952f9 --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_publicipprefix/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_azure diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_publicipprefix/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_publicipprefix/tasks/main.yml new file mode 100644 index 000000000..d229bc68b --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_publicipprefix/tasks/main.yml @@ -0,0 +1,102 @@ +- name: Create random variable + ansible.builtin.set_fact: + rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" + +- name: Create public ip prefix (Check mode) + azure_rm_publicipprefix: + resource_group: "{{ resource_group }}" + name: "pipprefix{{ rpfx }}" + zones: + - 1 + public_ip_address_version: IPV4 + prefix_length: 29 + sku: + name: Standard + tier: Regional + tags: + testing: testing + check_mode: true + +- name: Create public ip prefix + azure_rm_publicipprefix: + resource_group: "{{ resource_group }}" + name: "pipprefix{{ rpfx }}" + zones: + - 1 + public_ip_address_version: IPV4 + prefix_length: 29 + sku: + name: Standard + tier: Regional + tags: + testing: testing + register: output + +- name: Assert the public IP prefix is well created + ansible.builtin.assert: + that: + - output.changed + +- name: Create public ip prefix (Idempotent test) + azure_rm_publicipprefix: + resource_group: "{{ resource_group }}" + name: "pipprefix{{ rpfx }}" + zones: + - 1 + public_ip_address_version: IPV4 + prefix_length: 29 + sku: + name: Standard + tier: Regional + tags: + testing: testing + register: output + +- name: Assert the public IP prefix no change + ansible.builtin.assert: + that: + - not output.changed + +- name: Update public ip prefix (Update tags) + azure_rm_publicipprefix: + resource_group: "{{ resource_group }}" + name: "pipprefix{{ rpfx }}" + zones: + - 1 + public_ip_address_version: IPV4 + prefix_length: 29 + sku: + name: Standard + tier: Regional + tags: + testing2: testing2 + register: output + +- name: Assert the public IP prefix change + ansible.builtin.assert: + that: + - output.changed + +- name: Gather facts for a public ip prefix + azure_rm_publicipprefix_info: + resource_group: "{{ resource_group }}" + name: "pipprefix{{ rpfx }}" + register: output + +- name: Assert the public IP prefix facts + ansible.builtin.assert: + that: + - output.publicipprefixes[0].tags | length == 2 + - output.publicipprefixes[0].prefix_length == 29 + +- name: Delete the public IP prefix + azure_rm_publicipprefix: + resource_group: "{{ resource_group }}" + name: "pipprefix{{ rpfx }}" + state: absent + register: output + +- name: Assert the public IP prefix deleted + ansible.builtin.assert: + that: + - output.changed diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_registrationassignment/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_registrationassignment/tasks/main.yml index 05cc5d552..f1b2adca7 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_registrationassignment/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_registrationassignment/tasks/main.yml @@ -64,7 +64,7 @@ - name: Assert the registration assignment facts ansible.builtin.assert: that: - - output.registration_assignments[0].properties.registration_definition_id == "{{ output1.state.id }}" + - output.registration_assignments[0].properties.registration_definition_id == output1.state.id - name: Get all RegistrationAssignment azure_rm_registrationassignment_info: diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_registrationdefinition/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_registrationdefinition/tasks/main.yml index 3a5d58143..60093bc9f 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_registrationdefinition/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_registrationdefinition/tasks/main.yml @@ -100,7 +100,7 @@ - name: Assert the registration definition info ansible.builtin.assert: that: - - output.registration_definitions[0].name == "{{ output1.state.name }}" + - output.registration_definitions[0].name == output1.state.name - output.registration_definitions[0].properties.authorizations[0].principal_id == "{{ principal_id }}" - output.registration_definitions[0].properties.authorizations[0].role_definition_id == "{{ role_definition_id }}" - output.registration_definitions[0].properties.provisioning_state == "Succeeded" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_roleassignment/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_roleassignment/tasks/main.yml index e918bdc19..00cf42cf9 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_roleassignment/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_roleassignment/tasks/main.yml @@ -1,6 +1,6 @@ - name: Setup basic facts ansible.builtin.set_fact: - uuid: bb21a88b-30e1-42b5-84e8-1d3f322de033 + uuid: "{{ (2**128) | random | to_uuid }}" # Disk Backup Reader, unlikely to be already assigned in ansible-test resource groups. az_role_definition_guid: '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24' diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_securitygroup/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_securitygroup/tasks/main.yml index 6dc584a6f..af71a3046 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_securitygroup/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_securitygroup/tasks/main.yml @@ -33,7 +33,8 @@ register: output - name: Assert resource created ansible.builtin.assert: - that: "{{ output.state.rules | length }} == 2" + that: + - output.state.rules | length == 2 - name: Gather facts by tags azure_rm_securitygroup_info: @@ -80,7 +81,7 @@ - name: Assert resource updated ansible.builtin.assert: that: - - "{{ output.state.rules | length }} == 4" + - output.state.rules | length== 4 - output.state.rules[0].source_address_prefix == '174.108.158.0/24' - name: Gather facts after update @@ -197,8 +198,8 @@ - name: Assert resource created ansible.builtin.assert: that: - - "{{ output.state.rules | length }} == 1" - - "{{ output.state.rules[0].source_address_prefixes | length }} == 3" + - output.state.rules | length == 1 + - output.state.rules[0].source_address_prefixes | length == 3 - not output.state.rules[0].source_address_prefix - name: Create security group with source_address_prefixes(idempotent) @@ -248,7 +249,7 @@ ansible.builtin.assert: that: - output.changed - - "{{ output.state.rules | length }} == 2" + - output.state.rules | length == 2 # Use azure_rm_resource module to create with uppercase protocol name - name: Create security group with uppercase protocol name diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_sshpublickey/aliases b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_sshpublickey/aliases new file mode 100644 index 000000000..5d29c6c4d --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_sshpublickey/aliases @@ -0,0 +1,3 @@ +cloud/azure +shippable/azure/group10 +destructive diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_sshpublickey/meta/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_sshpublickey/meta/main.yml new file mode 100644 index 000000000..95e1952f9 --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_sshpublickey/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_azure diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_sshpublickey/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_sshpublickey/tasks/main.yml new file mode 100644 index 000000000..fa7981b52 --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_sshpublickey/tasks/main.yml @@ -0,0 +1,70 @@ +- name: Prepare random number + ansible.builtin.set_fact: + rpfx: "{{ resource_group | hash('md5') | truncate(7, True, '') }}{{ 1000 | random }}" + +- name: Create a new SSH Public Key + azure_rm_sshpublickey: + resource_group: "{{ resource_group }}" + name: sshpublic{{ rpfx }} + public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCoit3vZKD1Nf6ZZQImq5sRiv0r986/oz+zBezfXPWVKiCgy1TIyX+kGuMNhXcS9rTelXmIo2g3hvw2P/elSilaNkmuDE9otszATeOjPORoIrTcEd2N7vZUpwP7Ekmp+OZ/4ROG4dEuD2PVygmajYvNAayU8Ghdk/sAqLSOJ5FoPa3DO/1JUX81VzFQyfwtcstCsUouIft0GQ0QbSrXEMmtqylU/TstQZdupdWLxaLLRyTb57X43FUWM28lC/HczCPE3TX8gxZAzPTwA7yWp8Mum+QLC7IiKEAMbyVotzbtkcWU6BJd8uOGEQaHbJqoXOhmPKFMdHyhmT43fckS2mh6dSU0z8WiNC/CyCtsavZy0LSXEyPWL1bTDouHePygPXd1sN1GhCtk65tPYncbZavFuI7PcN0yxpjZWATdP79TU5cPYwZl2SZMhtBrR/ll/HLP88CgXIqZ1wsLM+ek76WqHLlhA5UK7KSE8z2qOdnsmH8uTRe4MrqmM9C5VCgjS18= test@test.com" + tags: + key1: value1 + key2: value2 + register: output + +- name: Assert the SSH Public Key created + ansible.builtin.assert: + that: + - output.changed + +- name: Create a new SSH Public Key (Idempotent test) + azure_rm_sshpublickey: + resource_group: "{{ resource_group }}" + name: sshpublic{{ rpfx }} + public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCoit3vZKD1Nf6ZZQImq5sRiv0r986/oz+zBezfXPWVKiCgy1TIyX+kGuMNhXcS9rTelXmIo2g3hvw2P/elSilaNkmuDE9otszATeOjPORoIrTcEd2N7vZUpwP7Ekmp+OZ/4ROG4dEuD2PVygmajYvNAayU8Ghdk/sAqLSOJ5FoPa3DO/1JUX81VzFQyfwtcstCsUouIft0GQ0QbSrXEMmtqylU/TstQZdupdWLxaLLRyTb57X43FUWM28lC/HczCPE3TX8gxZAzPTwA7yWp8Mum+QLC7IiKEAMbyVotzbtkcWU6BJd8uOGEQaHbJqoXOhmPKFMdHyhmT43fckS2mh6dSU0z8WiNC/CyCtsavZy0LSXEyPWL1bTDouHePygPXd1sN1GhCtk65tPYncbZavFuI7PcN0yxpjZWATdP79TU5cPYwZl2SZMhtBrR/ll/HLP88CgXIqZ1wsLM+ek76WqHLlhA5UK7KSE8z2qOdnsmH8uTRe4MrqmM9C5VCgjS18= test@test.com" + tags: + key1: value1 + key2: value2 + register: output + +- name: Assert the SSH Public key no changed + ansible.builtin.assert: + that: + - not output.changed + +- name: Update SSH Public Key with tags and public key + azure_rm_sshpublickey: + resource_group: "{{ resource_group }}" + name: sshpublic{{ rpfx }} + public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCoit3vZKD1Nf6ZZQImq5sRiv0r986/oz+zBezfXPWVKiCgy1TIyX+kGuMNhXcS9rTelXmIo2g3hvw2P/elSilaNkmuDE9otszATeOjPORoIrTcEd2N7vZUpwP7Ekmp+OZ/4ROG4dEuD2PVygmajYvNAayU8Ghdk/sAqLSOJ5FoPa3DO/1JUX81VzFQyfwtcstCsUouIft0GQ0QbSrXEMmtqylU/TstQZdupdWLxaLLRyTb57X43FUWM28lC/HczCPE3TX8gxZAzPTwA7yWp8Mum+QLC7IiKEAMbyVotzbtkcWU6BJd8uOGEQaHbJqoXOhmPKFMdHyhmT43fckS2mh6dSU0z8WiNC/CyCtsavZy0LSXEyPWL1bTDouHePygPXd1sN1GhCtk65tPYncbZavFuI7PcN0yxpjZWATdP79TU5cPYwZl2SZMhtBrR/ll/HLP88CgXIqZ1wsLM+ek76WqHLlhA5UK7KSE8z2qOdnsmH8uTRe4MrqmM9C5VCgjS18= test@test.com" + tags: + key3: value3 + register: output + +- name: Assert the SSH Public key Updated + ansible.builtin.assert: + that: + - output.changed + +- name: Get ssh public keys by name + azure_rm_sshpublickey_info: + resource_group: "{{ resource_group }}" + name: sshpublic{{ rpfx }} + register: output + +- name: Assert the SSH Public Kyes facts + ansible.builtin.assert: + that: + - output.ssh_keys[0].tags | length == 3 + +- name: Delete a new SSH Public Key + azure_rm_sshpublickey: + resource_group: "{{ resource_group }}" + name: sshpublic{{ rpfx }} + state: absent + register: output + +- name: Assert the SSH Public Key deleted + ansible.builtin.assert: + that: + - output.changed diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_storageaccount/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_storageaccount/tasks/main.yml index dfeabed07..942d4888a 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_storageaccount/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_storageaccount/tasks/main.yml @@ -139,6 +139,7 @@ resource_group: "{{ resource_group }}" name: "{{ storage_account_name_default }}06" account_type: Standard_LRS + large_file_shares_state: Enabled kind: StorageV2 is_hns_enabled: true register: output @@ -146,6 +147,7 @@ ansible.builtin.assert: that: - output.changed + - output.state.large_file_shares_state == 'Enabled' - name: Gather facts of storage account azure_rm_storageaccount_info: @@ -157,6 +159,7 @@ that: - "output.storageaccounts | length == 1" - output.storageaccounts[0].is_hns_enabled == true + - output.storageaccounts[0].large_file_shares_state == 'Enabled' - name: Create storage account with static website enabled azure_rm_storageaccount: @@ -598,3 +601,4 @@ - "{{ storage_account_name_default }}03" - "{{ storage_account_name_default }}04" - "{{ storage_account_name_default }}05" + - "{{ storage_account_name_default }}06" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_storageblob/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_storageblob/tasks/main.yml index 307d52d27..98cd3dc38 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_storageblob/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_storageblob/tasks/main.yml @@ -11,12 +11,14 @@ - name: Create container azure_rm_storageblob: + auth_mode: login resource_group: "{{ resource_group }}" account_name: "{{ storage_account }}" container_name: my-blobs - name: Force upload blob azure_rm_storageblob: + auth_mode: login resource_group: "{{ resource_group }}" account_name: "{{ storage_account }}" container_name: my-blobs diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_trafficmanagerprofile/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_trafficmanagerprofile/tasks/main.yml index 6e2a7f342..e1b93935d 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_trafficmanagerprofile/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_trafficmanagerprofile/tasks/main.yml @@ -33,7 +33,9 @@ register: fact - name: Check there is no Traffic Manager profile created - ansible.builtin.assert: { that: "{{ fact.tms | length }} == 0" } + ansible.builtin.assert: + that: + - fact.tms | length == 0 - name: Create a Traffic Manager profile azure_rm_trafficmanagerprofile: @@ -69,7 +71,7 @@ - name: Assert fact returns the created one ansible.builtin.assert: that: - - "fact.tms | length == 1" + - fact.tms | length == 1 - fact.tms[0].id == tm.id - fact.tms[0].endpoints | length == 0 @@ -261,7 +263,7 @@ - name: Assert the traffic manager profile is still there ansible.builtin.assert: that: - - "fact.tms | length == 1" + - fact.tms | length == 1 - fact.tms[0].id == tm.id - fact.tms[0].endpoints | length == 1 @@ -286,4 +288,4 @@ - name: Assert fact returns empty ansible.builtin.assert: that: - - "fact.tms | length == 0" + - fact.tms | length == 0 diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/inventory.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/inventory.yml index 88172852a..63ba77727 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/inventory.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/inventory.yml @@ -40,6 +40,10 @@ all: network: 10.42.7.0/24 subnet: 10.42.7.0/28 + azure_test_encrypted: + network: 10.42.8.0/24 + subnet: 10.42.8.0/28 + vars: ansible_connection: local ansible_python_interpreter: "{{ ansible_playbook_python }}" @@ -55,6 +59,7 @@ all: security_group: "{{ 'sg' ~ uid_short }}" public_ip_name: "{{ 'ip' ~ uid_short }}" interface_name: "{{ 'int' ~ uid_short }}" + des_name: "{{ 'des' ~ uid_short }}" ssh_keys: - path: '/home/chouseknecht/.ssh/authorized_keys' diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_deallocate.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_deallocate.yml index 09bb56e9c..e1ba515d7 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_deallocate.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_deallocate.yml @@ -25,10 +25,6 @@ name: "{{ vm_name }}" register: vm_state -- name: Pause for 10 mimutes to VM updating - ansible.builtin.command: sleep 600 - changed_when: true - - name: Restart the virtual machine azure_rm_virtualmachine: resource_group: "{{ resource_group }}" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_dual_nic.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_dual_nic.yml index f6865b2e7..c2802868e 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_dual_nic.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_dual_nic.yml @@ -118,10 +118,6 @@ name: "{{ vm_name }}" register: vm_state -- name: Pause for 10 mimutes to VM updating - ansible.builtin.command: sleep 600 - changed_when: true - - name: Generalize VM azure_rm_virtualmachine: resource_group: "{{ resource_group }}" # Should this be resource_group_secondary? diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_encrypted.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_encrypted.yml new file mode 100644 index 000000000..c43d09a61 --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_encrypted.yml @@ -0,0 +1,107 @@ +- name: Set variables + ansible.builtin.include_tasks: setup.yml + +- name: Set up disk encryption sets + ansible.builtin.include_tasks: setup_des.yml + +- name: Create VM with encrypted disks + azure_rm_virtualmachine: + resource_group: "{{ resource_group }}" + name: "{{ vm_name }}" + admin_username: "testuser" + ssh_password_enabled: false + ssh_public_keys: + - path: /home/testuser/.ssh/authorized_keys + key_data: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDfoYlIV4lTPZTv7hXaVwQQuqBgGs4yeNRX0SPo2+HQt9u4X7IGwrtXc0nEUm6LfaCikMH58bOL8f20NTGz285kxdFHZRcBXtqmnMz2rXwhK9gwq5h1khc+GzHtdcJXsGA4y0xuaNcidcg04jxAlN/06fwb/VYwwWTVbypNC0gpGEpWckCNm8vlDlA55sU5et0SZ+J0RKVvEaweUOeNbFZqckGPA384imfeYlADppK/7eAxqfBVadVvZG8IJk4yvATgaIENIFj2cXxqu2mQ/Bp5Wr45uApvJsFXmi+v/nkiOEV1QpLOnEwAZo6EfFS4CCQtsymxJCl1PxdJ5LD4ZOtP xiuxi.sun@qq.com" + vm_size: Standard_B1ms + virtual_network: "{{ network_name }}" + os_disk_encryption_set: "{{ des_results.state.id }}" + managed_disk_type: Standard_LRS + image: + offer: 0001-com-ubuntu-server-focal + publisher: Canonical + sku: 20_04-lts + version: latest + register: vm_output + +- name: Query auto created security group before deleting + azure_rm_securitygroup_info: + resource_group: "{{ resource_group }}" + name: "{{ vm_name }}01" + register: nsg_result + +- name: Assert that security group were exist before deleting + ansible.builtin.assert: + that: + - nsg_result.securitygroups | length == 1 + - nsg_result.securitygroups[0].network_interfaces | length == 1 + +- name: Delete VM + azure_rm_virtualmachine: + resource_group: "{{ resource_group }}" + name: "{{ vm_name }}" + remove_on_absent: all_autocreated + state: absent + +- name: Destroy encrypted OS disk + azure_rm_manageddisk: + resource_group: "{{ resource_group }}" + name: "{{ vm_name }}" + state: absent + +- name: Destroy auto created NIC + azure_rm_networkinterface: + resource_group: "{{ resource_group }}" + name: "{{ vm_name }}01" + state: absent + register: nic_result + +- name: Destroy security group + azure_rm_securitygroup: + resource_group: "{{ resource_group }}" + name: "{{ vm_name }}01" + state: absent + +- name: Destroy auto created public IP + azure_rm_publicipaddress: + resource_group: "{{ resource_group }}" + name: "{{ vm_name }}01" + state: absent + +- name: Destroy subnet + azure_rm_subnet: + resource_group: "{{ resource_group }}" + virtual_network: "{{ network_name }}" + name: "{{ subnet_name }}" + state: absent + +- name: Destroy virtual network + azure_rm_virtualnetwork: + resource_group: "{{ resource_group }}" + name: "{{ network_name }}" + state: absent + +- name: Destroy availability set + azure_rm_availabilityset: + resource_group: "{{ resource_group }}" + name: "{{ availability_set }}" + state: absent + +- name: Destroy storage account + azure_rm_storageaccount: + resource_group: "{{ resource_group }}" + name: "{{ storage_account }}" + force_delete_nonempty: true + state: absent + +- name: Destroy disk encryption set + azure_rm_diskencryptionset: + resource_group: "{{ resource_group }}" + name: "{{ des_name }}" + state: absent + +- name: Destroy key vault + azure_rm_keyvault: + vault_name: "{{ vault_name }}" + resource_group: "{{ resource_group }}" + state: absent diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_ephemeral_os.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_ephemeral_os.yml index 1b18c71ef..cbb184ef3 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_ephemeral_os.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_ephemeral_os.yml @@ -32,10 +32,6 @@ name: "{{ vm_name }}" register: vm_state -- name: Pause for 10 mimutes to VM updating - ansible.builtin.command: sleep 600 - changed_when: true - - name: Generalize VM azure_rm_virtualmachine: resource_group: "{{ resource_group }}" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_public_ip.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_public_ip.yml index 2ee786b34..f24be88e2 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_public_ip.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/azure_test_public_ip.yml @@ -92,10 +92,6 @@ name: "{{ vm_name }}" register: vm_state -- name: Pause for 10 mimutes to VM updating - ansible.builtin.command: sleep 600 - changed_when: true - - name: Enable boot diagnostics on an existing VM for the first time without specifying a storage account azure_rm_virtualmachine: resource_group: "{{ resource_group }}" diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/setup_des.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/setup_des.yml new file mode 100644 index 000000000..afdde8440 --- /dev/null +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachine/tasks/setup_des.yml @@ -0,0 +1,94 @@ +- name: Set vault name + ansible.builtin.set_fact: + vault_name: "kv{{ uid_short }}{{ '%m%d%H%M%S' | strftime }}" + +- name: Lookup service principal object id + ansible.builtin.set_fact: + object_id: "{{ lookup('azure.azcollection.azure_service_principal_attribute', + azure_client_id=azure_client_id, + azure_secret=azure_secret, + azure_tenant=azure_tenant) }}" + register: object_id_facts + +- name: Create a key vault + azure_rm_keyvault: + resource_group: "{{ resource_group }}" + vault_name: "{{ vault_name }}" + enabled_for_disk_encryption: true + enable_purge_protection: true + vault_tenant: "{{ azure_tenant }}" + sku: + name: standard + family: A + access_policies: + - tenant_id: "{{ azure_tenant }}" + object_id: "{{ object_id }}" + keys: + - get + - list + - wrapkey + - unwrapkey + - create + - update + - import + - delete + - backup + - restore + - recover + - purge + +- name: Create a key in key vault + azure_rm_keyvaultkey: + key_name: testkey + keyvault_uri: https://{{ vault_name }}.vault.azure.net + +- name: Get latest version of key + azure_rm_keyvaultkey_info: + vault_uri: https://{{ vault_name }}.vault.azure.net + name: testkey + register: results + +- name: Assert the key vault facts + ansible.builtin.set_fact: + key_url: "{{ results['keys'][0]['kid'] }}" + +- name: Create disk encryption set + azure_rm_diskencryptionset: + resource_group: "{{ resource_group }}" + name: "{{ des_name }}" + source_vault: "{{ vault_name }}" + key_url: "{{ key_url }}" + state: present + register: des_results + +- name: Grant DES access to key vault + azure_rm_keyvault: + resource_group: "{{ resource_group }}" + vault_name: "{{ vault_name }}" + enabled_for_disk_encryption: true + enable_purge_protection: true + vault_tenant: "{{ azure_tenant }}" + sku: + name: standard + family: A + access_policies: + - tenant_id: "{{ azure_tenant }}" + object_id: "{{ object_id }}" + keys: + - get + - list + - wrapkey + - unwrapkey + - create + - update + - import + - delete + - backup + - restore + - recover + - purge + - object_id: "{{ des_results.state.identity.principal_id }}" + keys: + - get + - wrapkey + - unwrapkey diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml index 98f51ee9f..c3c5336ae 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_virtualmachinescaleset/tasks/main.yml @@ -21,24 +21,28 @@ resource_group: "{{ resource_group }}" allocation_method: Static name: testPublicIP + sku: Standard - name: Create load balancer azure_rm_loadbalancer: resource_group: "{{ resource_group }}" name: testLB public_ip_address_name: testPublicIP + sku: Standard - name: Create public IP address 1 azure_rm_publicipaddress: resource_group: "{{ resource_group }}" allocation_method: Static name: testPublicIP1 + sku: Standard - name: Create load balancer 1 azure_rm_loadbalancer: resource_group: "{{ resource_group }}" name: testLB1 public_ip_address_name: testPublicIP1 + sku: Standard - name: Create network security group within same resource group of VMSS. azure_rm_securitygroup: @@ -78,9 +82,6 @@ resource_group: "{{ resource_group }}" name: "vmforimage{{ rpfx }}" register: vm_state -- name: Pause for 10 mimutes to VM updating - ansible.builtin.command: sleep 600 - changed_when: true - name: Generalize VM azure_rm_virtualmachine: resource_group: "{{ resource_group }}" @@ -196,6 +197,7 @@ priority: Spot eviction_policy: Deallocate single_placement_group: true + orchestration_mode: Uniform ssh_password_enabled: false ssh_public_keys: - path: /home/testuser/.ssh/authorized_keys @@ -253,6 +255,7 @@ managed_disk_type: Standard_LRS os_disk_caching: ReadWrite single_placement_group: true + orchestration_mode: Uniform image: offer: 0001-com-ubuntu-server-focal publisher: Canonical @@ -297,6 +300,7 @@ managed_disk_type: Standard_LRS os_disk_caching: ReadWrite single_placement_group: true + orchestration_mode: Uniform image: offer: 0001-com-ubuntu-server-focal publisher: Canonical @@ -346,6 +350,7 @@ os_disk_caching: ReadWrite custom_data: "#cloud-config" single_placement_group: true + orchestration_mode: Uniform image: offer: 0001-com-ubuntu-server-focal publisher: Canonical @@ -383,6 +388,7 @@ os_disk_caching: ReadWrite custom_data: "#cloud-config" single_placement_group: true + orchestration_mode: Uniform image: offer: 0001-com-ubuntu-server-focal publisher: Canonical @@ -455,6 +461,7 @@ data_disks: "{{ body.data_disks }}" overprovision: "{{ body.overprovision }}" single_placement_group: true + orchestration_mode: Uniform register: results - name: Assert that nothing was changed @@ -608,6 +615,7 @@ security_group: testNetworkSecurityGroup enable_accelerated_networking: true single_placement_group: true + orchestration_mode: Uniform register: results check_mode: true @@ -635,6 +643,7 @@ security_group: testNetworkSecurityGroup enable_accelerated_networking: true single_placement_group: true + orchestration_mode: Uniform register: results - name: Assert that VMSS ran @@ -664,6 +673,7 @@ security_group: testNetworkSecurityGroup enable_accelerated_networking: true single_placement_group: true + orchestration_mode: Uniform register: results - name: Assert that nothing has changed @@ -691,6 +701,7 @@ security_group: testNetworkSecurityGroup enable_accelerated_networking: true single_placement_group: true + orchestration_mode: Uniform register: results - name: Assert that something has changed @@ -719,6 +730,7 @@ name: testNetworkSecurityGroup2 resource_group: "{{ resource_group_secondary }}" single_placement_group: true + orchestration_mode: Uniform register: results # disable for now @@ -756,6 +768,7 @@ name: testNetworkSecurityGroup2 resource_group: "{{ resource_group_secondary }}" single_placement_group: true + orchestration_mode: Uniform register: results - name: Assert vmss created @@ -786,6 +799,7 @@ name: testNetworkSecurityGroup2 resource_group: "{{ resource_group_secondary }}" single_placement_group: true + orchestration_mode: Uniform ignore_errors: true register: ignore_errors_register @@ -815,6 +829,7 @@ upgrade_policy: Manual enable_accelerated_networking: true single_placement_group: true + orchestration_mode: Uniform register: results ignore_errors: true diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_webapp/tasks/main.yml b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_webapp/tasks/main.yml index 42a3abe3c..6b8128eb3 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_webapp/tasks/main.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/azure_rm_webapp/tasks/main.yml @@ -83,7 +83,7 @@ plan: "{{ win_plan_name }}" frameworks: - name: "java" - version: "1.8" + version: "17" settings: java_container: "Tomcat" java_container_version: "8.0" @@ -115,7 +115,7 @@ plan: "{{ win_plan_name }}" frameworks: - name: "java" - version: "1.7" + version: "17" settings: java_container: "Tomcat" java_container_version: "8.5" @@ -230,7 +230,7 @@ name: "{{ linux_plan_name }}" frameworks: - name: node - version: "6.6" + version: "18" register: output - name: Should be idempotent with linux web app created @@ -242,7 +242,7 @@ name: "{{ linux_plan_name }}" frameworks: - name: node - version: "6.6" + version: "18" register: output - name: Assert idempotent @@ -258,7 +258,7 @@ name: "{{ linux_plan_name }}" frameworks: - name: node - version: "6.9" + version: "20" register: output - name: Assert the web app was created @@ -300,9 +300,9 @@ plan: "{{ win_plan_name }}" frameworks: - name: "python" - version: "2.7" + version: "3.11" - name: "java" - version: "1.8" + version: "17" register: fail_win_java_version_mutual_exclusive failed_when: 'fail_win_java_version_mutual_exclusive.msg != "Java is mutually exclusive with other frameworks."' @@ -315,9 +315,9 @@ name: "{{ linux_plan_name }}" frameworks: - name: "python" - version: "2.7" + version: "3.11" - name: "node" - version: "6.6" + version: "18" register: fail_linux_one_framework_only failed_when: fail_linux_one_framework_only.msg != "Can specify one framework only for Linux web app." @@ -354,7 +354,7 @@ - name: Create a web app with various site config params azure_rm_webapp: - resource_group: "{{ resource_group }}" + resource_group: "{{ linux_app_plan_resource_group }}" name: "{{ linux_app_name }}-siteconfig" plan: resource_group: "{{ linux_app_plan_resource_group }}" @@ -379,7 +379,7 @@ - name: Create a web app with various site config params - idempotent azure_rm_webapp: - resource_group: "{{ resource_group }}" + resource_group: "{{ linux_app_plan_resource_group }}" name: "{{ linux_app_name }}-siteconfig" plan: resource_group: "{{ linux_app_plan_resource_group }}" @@ -404,7 +404,7 @@ - name: Get facts for site config params azure_rm_webapp_info: - resource_group: "{{ resource_group }}" + resource_group: "{{ linux_app_plan_resource_group }}" name: "{{ linux_app_name }}-siteconfig" register: facts - name: Assert site config params meet expectations @@ -413,10 +413,11 @@ - facts.webapps[0].always_on - facts.webapps[0].min_tls_version == '1.2' - facts.webapps[0].ftps_state == 'Disabled' + - not facts.webapps[0].http20_enabled - name: Update web app with various site config params - single change azure_rm_webapp: - resource_group: "{{ resource_group }}" + resource_group: "{{ linux_app_plan_resource_group }}" name: "{{ linux_app_name }}-siteconfig" plan: resource_group: "{{ linux_app_plan_resource_group }}" @@ -441,7 +442,7 @@ - name: Get facts for site config params azure_rm_webapp_info: - resource_group: "{{ resource_group }}" + resource_group: "{{ linux_app_plan_resource_group }}" name: "{{ linux_app_name }}-siteconfig" register: facts - name: Assert site config params meet expectations @@ -450,6 +451,111 @@ - facts.webapps[0].always_on - facts.webapps[0].min_tls_version == '1.2' - facts.webapps[0].ftps_state == 'FtpsOnly' + - not facts.webapps[0].http20_enabled + +- name: Create a web app with HTTP 2.0 + azure_rm_webapp: + resource_group: "{{ linux_app_plan_resource_group }}" + name: "{{ linux_app_name }}-http20" + plan: + resource_group: "{{ linux_app_plan_resource_group }}" + name: "{{ linux_app_name }}-http20-plan" + is_linux: true + sku: S1 + frameworks: + - name: java + version: "8" + settings: + java_container: "tomcat" + java_container_version: "8.5" + client_affinity_enabled: false + https_only: true + always_on: true + min_tls_version: "1.2" + ftps_state: "Disabled" + http20_enabled: true + register: output +- name: Assert the web app was created + ansible.builtin.assert: + that: output.changed + +- name: Create a web app with HTTP 2.0 - idempotent + azure_rm_webapp: + resource_group: "{{ linux_app_plan_resource_group }}" + name: "{{ linux_app_name }}-http20" + plan: + resource_group: "{{ linux_app_plan_resource_group }}" + name: "{{ linux_app_name }}-http20-plan" + is_linux: true + sku: S1 + frameworks: + - name: java + version: "8" + settings: + java_container: "tomcat" + java_container_version: "8.5" + client_affinity_enabled: false + https_only: true + always_on: true + min_tls_version: "1.2" + ftps_state: "Disabled" + http20_enabled: true + register: output +- name: Assert the web app not changed + ansible.builtin.assert: + that: not output.changed + +- name: Get facts for HTTP 2.0 appp + azure_rm_webapp_info: + resource_group: "{{ linux_app_plan_resource_group }}" + name: "{{ linux_app_name }}-http20" + register: facts +- name: Assert site config params meet expectations + ansible.builtin.assert: + that: + - facts.webapps[0].always_on + - facts.webapps[0].min_tls_version == '1.2' + - facts.webapps[0].ftps_state == 'Disabled' + - facts.webapps[0].http20_enabled + +- name: Update web app to disable HTTP 2.0 + azure_rm_webapp: + resource_group: "{{ linux_app_plan_resource_group }}" + name: "{{ linux_app_name }}-http20" + plan: + resource_group: "{{ linux_app_plan_resource_group }}" + name: "{{ linux_app_name }}-http20-plan" + is_linux: true + sku: S1 + frameworks: + - name: java + version: "8" + settings: + java_container: "tomcat" + java_container_version: "8.5" + client_affinity_enabled: false + https_only: true + always_on: true + min_tls_version: "1.2" + ftps_state: "Disabled" + http20_enabled: false + register: output +- name: Assert the web app was updated + ansible.builtin.assert: + that: output.changed + +- name: Get facts for HTTP 2.0 appp + azure_rm_webapp_info: + resource_group: "{{ linux_app_plan_resource_group }}" + name: "{{ linux_app_name }}-http20" + register: facts +- name: Assert site config params meet expectations + ansible.builtin.assert: + that: + - facts.webapps[0].always_on + - facts.webapps[0].min_tls_version == '1.2' + - facts.webapps[0].ftps_state == 'Disabled' + - not facts.webapps[0].http20_enabled - name: Create a webapp slot (Check mode) azure_rm_webappslot: diff --git a/ansible_collections/azure/azcollection/tests/integration/targets/inventory_azure/playbooks/test_inventory.yml b/ansible_collections/azure/azcollection/tests/integration/targets/inventory_azure/playbooks/test_inventory.yml index b00e48247..acfed0606 100644 --- a/ansible_collections/azure/azcollection/tests/integration/targets/inventory_azure/playbooks/test_inventory.yml +++ b/ansible_collections/azure/azcollection/tests/integration/targets/inventory_azure/playbooks/test_inventory.yml @@ -7,10 +7,6 @@ - name: Set facts ansible.builtin.include_vars: vars.yml - - name: Pause for 10 mimutes for updating - ansible.builtin.command: sleep 600 - changed_when: false - - name: Refresh inventory ansible.builtin.meta: refresh_inventory diff --git a/ansible_collections/azure/azcollection/tests/sanity/ignore-2.13.txt b/ansible_collections/azure/azcollection/tests/sanity/ignore-2.13.txt deleted file mode 100644 index 44a2ab267..000000000 --- a/ansible_collections/azure/azcollection/tests/sanity/ignore-2.13.txt +++ /dev/null @@ -1,18 +0,0 @@ -plugins/modules/azure_rm_apimanagement.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_dnsrecordset.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_gallery.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_galleryimage.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_galleryimageversion.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_managementgroup.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_registrationdefinition.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_registrationassignment.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_virtualwan.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_snapshot.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_vpnsite.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_batchaccount.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_azurefirewall.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_apimanagementservice.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_openshiftmanagedcluster.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_privatednsrecordset.py validate-modules:invalid-ansiblemodule-schema -tests/utils/shippable/check_matrix.py replace-urlopen -tests/utils/shippable/timing.py shebang diff --git a/ansible_collections/azure/azcollection/tests/sanity/ignore-2.14.txt b/ansible_collections/azure/azcollection/tests/sanity/ignore-2.14.txt deleted file mode 100644 index 44a2ab267..000000000 --- a/ansible_collections/azure/azcollection/tests/sanity/ignore-2.14.txt +++ /dev/null @@ -1,18 +0,0 @@ -plugins/modules/azure_rm_apimanagement.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_dnsrecordset.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_gallery.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_galleryimage.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_galleryimageversion.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_managementgroup.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_registrationdefinition.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_registrationassignment.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_virtualwan.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_snapshot.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_vpnsite.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_batchaccount.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_azurefirewall.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_apimanagementservice.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_openshiftmanagedcluster.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_privatednsrecordset.py validate-modules:invalid-ansiblemodule-schema -tests/utils/shippable/check_matrix.py replace-urlopen -tests/utils/shippable/timing.py shebang diff --git a/ansible_collections/azure/azcollection/tests/sanity/ignore-2.15.txt b/ansible_collections/azure/azcollection/tests/sanity/ignore-2.15.txt deleted file mode 100644 index 44a2ab267..000000000 --- a/ansible_collections/azure/azcollection/tests/sanity/ignore-2.15.txt +++ /dev/null @@ -1,18 +0,0 @@ -plugins/modules/azure_rm_apimanagement.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_dnsrecordset.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_gallery.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_galleryimage.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_galleryimageversion.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_managementgroup.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_registrationdefinition.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_registrationassignment.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_virtualwan.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_snapshot.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_vpnsite.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_batchaccount.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_azurefirewall.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_apimanagementservice.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_openshiftmanagedcluster.py validate-modules:invalid-ansiblemodule-schema -plugins/modules/azure_rm_privatednsrecordset.py validate-modules:invalid-ansiblemodule-schema -tests/utils/shippable/check_matrix.py replace-urlopen -tests/utils/shippable/timing.py shebang diff --git a/ansible_collections/azure/azcollection/tests/utils/ado/ado.sh b/ansible_collections/azure/azcollection/tests/utils/ado/ado.sh index bd8a195b3..4bae8b5d4 100755 --- a/ansible_collections/azure/azcollection/tests/utils/ado/ado.sh +++ b/ansible_collections/azure/azcollection/tests/utils/ado/ado.sh @@ -69,7 +69,7 @@ pip install -I -r "${TEST_DIR}/sanity-requirements-azure.txt" pip install ansible-lint -timeout=90 +timeout=180 if [ "$4" = "all" ] then diff --git a/ansible_collections/azure/azcollection/tests/utils/shippable/check_matrix.py b/ansible_collections/azure/azcollection/tests/utils/shippable/check_matrix.py index 96a377589..614396581 100755 --- a/ansible_collections/azure/azcollection/tests/utils/shippable/check_matrix.py +++ b/ansible_collections/azure/azcollection/tests/utils/shippable/check_matrix.py @@ -9,7 +9,7 @@ import os import re import sys import time -from ansible.module_utils.urls import open_url as urlopen +from ansible.module_utils.urls import open_url try: from typing import NoReturn @@ -41,7 +41,7 @@ def main(): # type: () -> None for attempts_remaining in range(4, -1, -1): try: - jobs = json.loads(urlopen('https://api.shippable.com/jobs?runIds=%s' % run_id).read()) + jobs = json.loads(open_url('https://api.shippable.com/jobs?runIds=%s' % run_id).read()) if not isinstance(jobs, list): raise Exception('Shippable run %s data is not a list.' % run_id) diff --git a/ansible_collections/azure/azcollection/tests/utils/shippable/timing.py b/ansible_collections/azure/azcollection/tests/utils/shippable/timing.py index d9456855d..55728eab6 100755 --- a/ansible_collections/azure/azcollection/tests/utils/shippable/timing.py +++ b/ansible_collections/azure/azcollection/tests/utils/shippable/timing.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3.6 +#!/usr/bin/env python from __future__ import (absolute_import, division, print_function) __metaclass__ = type |