diff --git a/doc/ref/clouds/all/salt.cloud.clouds.azurearm.rst b/doc/ref/clouds/all/salt.cloud.clouds.azurearm.rst deleted file mode 100644 index 86c4b7eea76..00000000000 --- a/doc/ref/clouds/all/salt.cloud.clouds.azurearm.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.cloud.clouds.azurearm -========================== - -.. automodule:: salt.cloud.clouds.azurearm - :members: diff --git a/doc/ref/clouds/all/salt.cloud.clouds.msazure.rst b/doc/ref/clouds/all/salt.cloud.clouds.msazure.rst deleted file mode 100644 index 4b624291f46..00000000000 --- a/doc/ref/clouds/all/salt.cloud.clouds.msazure.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.cloud.clouds.msazure -========================= - -.. automodule:: salt.cloud.clouds.msazure - :members: diff --git a/doc/ref/file_server/all/salt.fileserver.azurefs.rst b/doc/ref/file_server/all/salt.fileserver.azurefs.rst deleted file mode 100644 index c1291ed9890..00000000000 --- a/doc/ref/file_server/all/salt.fileserver.azurefs.rst +++ /dev/null @@ -1,4 +0,0 @@ -salt.fileserver.azurefs -======================= - -.. automodule:: salt.fileserver.azurefs diff --git a/doc/ref/grains/all/salt.grains.metadata_azure.rst b/doc/ref/grains/all/salt.grains.metadata_azure.rst deleted file mode 100644 index 41cfa502969..00000000000 --- a/doc/ref/grains/all/salt.grains.metadata_azure.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.grains.metadata_azure -========================== - -.. automodule:: salt.grains.metadata_azure - :members: diff --git a/doc/ref/modules/all/salt.modules.azurearm_compute.rst b/doc/ref/modules/all/salt.modules.azurearm_compute.rst deleted file mode 100644 index f82507d2f99..00000000000 --- a/doc/ref/modules/all/salt.modules.azurearm_compute.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.modules.azurearm_compute -============================= - -.. automodule:: salt.modules.azurearm_compute - :members: diff --git a/doc/ref/modules/all/salt.modules.azurearm_dns.rst b/doc/ref/modules/all/salt.modules.azurearm_dns.rst deleted file mode 100644 index 23e33fa0ab9..00000000000 --- a/doc/ref/modules/all/salt.modules.azurearm_dns.rst +++ /dev/null @@ -1,6 +0,0 @@ -salt.modules.azurearm_dns -========================= - -.. automodule:: salt.modules.azurearm_dns - :members: - :undoc-members: diff --git a/doc/ref/modules/all/salt.modules.azurearm_network.rst b/doc/ref/modules/all/salt.modules.azurearm_network.rst deleted file mode 100644 index 957649d3ea7..00000000000 --- a/doc/ref/modules/all/salt.modules.azurearm_network.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.modules.azurearm_network -============================= - -.. automodule:: salt.modules.azurearm_network - :members: diff --git a/doc/ref/modules/all/salt.modules.azurearm_resource.rst b/doc/ref/modules/all/salt.modules.azurearm_resource.rst deleted file mode 100644 index c020a588350..00000000000 --- a/doc/ref/modules/all/salt.modules.azurearm_resource.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.modules.azurearm_resource -============================== - -.. automodule:: salt.modules.azurearm_resource - :members: diff --git a/doc/ref/pillar/all/salt.pillar.azureblob.rst b/doc/ref/pillar/all/salt.pillar.azureblob.rst deleted file mode 100644 index f47f5929d5f..00000000000 --- a/doc/ref/pillar/all/salt.pillar.azureblob.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.pillar.azureblob -===================== - -.. automodule:: salt.pillar.azureblob - :members: diff --git a/doc/ref/states/all/salt.states.azurearm_compute.rst b/doc/ref/states/all/salt.states.azurearm_compute.rst deleted file mode 100644 index 0f545fed4ef..00000000000 --- a/doc/ref/states/all/salt.states.azurearm_compute.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.azurearm_compute -============================ - -.. automodule:: salt.states.azurearm_compute - :members: diff --git a/doc/ref/states/all/salt.states.azurearm_dns.rst b/doc/ref/states/all/salt.states.azurearm_dns.rst deleted file mode 100644 index 29ebdb16d3d..00000000000 --- a/doc/ref/states/all/salt.states.azurearm_dns.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.azurearm_dns -======================== - -.. automodule:: salt.states.azurearm_dns - :members: diff --git a/doc/ref/states/all/salt.states.azurearm_network.rst b/doc/ref/states/all/salt.states.azurearm_network.rst deleted file mode 100644 index adc0754716e..00000000000 --- a/doc/ref/states/all/salt.states.azurearm_network.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.azurearm_network -============================ - -.. automodule:: salt.states.azurearm_network - :members: diff --git a/doc/ref/states/all/salt.states.azurearm_resource.rst b/doc/ref/states/all/salt.states.azurearm_resource.rst deleted file mode 100644 index 4ea24a8dde3..00000000000 --- a/doc/ref/states/all/salt.states.azurearm_resource.rst +++ /dev/null @@ -1,5 +0,0 @@ -salt.states.azurearm_resource -============================= - -.. automodule:: salt.states.azurearm_resource - :members: diff --git a/doc/topics/cloud/azure.rst b/doc/topics/cloud/azure.rst deleted file mode 100644 index 24598dec2e6..00000000000 --- a/doc/topics/cloud/azure.rst +++ /dev/null @@ -1,1481 +0,0 @@ -========================== -Getting Started With Azure -========================== - -.. versionadded:: 2014.1.0 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 due to - the deprecation of the "Classic" API for Azure. Please migrate to - `Azure Resource Manager by March 1, 2023 - `_ - -Azure is a cloud service by Microsoft providing virtual machines, SQL services, -media services, and more. This document describes how to use Salt Cloud to -create a virtual machine on Azure, with Salt installed. - -More information about Azure is located at `http://www.windowsazure.com/ -`_. - - -Dependencies -============ -* `Microsoft Azure SDK for Python `_ >= 1.0.2 -* The python-requests library, for Python < 2.7.9. -* A Microsoft Azure account -* OpenSSL (to generate the certificates) -* `Salt `_ - - -Configuration -============= - -Set up the provider config at ``/etc/salt/cloud.providers.d/azure.conf``: - -.. code-block:: yaml - - # Note: This example is for /etc/salt/cloud.providers.d/azure.conf - - my-azure-config: - driver: azure - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - certificate_path: /etc/salt/azure.pem - - # Set up the location of the salt master - # - minion: - master: saltmaster.example.com - - # Optional - management_host: management.core.windows.net - -The certificate used must be generated by the user. OpenSSL can be used to -create the management certificates. Two certificates are needed: a .cer file, -which is uploaded to Azure, and a .pem file, which is stored locally. - -To create the .pem file, execute the following command: - -.. code-block:: bash - - openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout /etc/salt/azure.pem -out /etc/salt/azure.pem - -To create the .cer file, execute the following command: - -.. code-block:: bash - - openssl x509 -inform pem -in /etc/salt/azure.pem -outform der -out /etc/salt/azure.cer - -After creating these files, the .cer file will need to be uploaded to -Azure via the "Upload a Management Certificate" action of the "Management Certificates" -tab within the "Settings" section of the management portal. - -Optionally, a ``management_host`` may be configured, if necessary for the region. - -.. note:: - .. versionchanged:: 2015.8.0 - - The ``provider`` parameter in cloud provider definitions was renamed to ``driver``. This - change was made to avoid confusion with the ``provider`` parameter that is used in cloud profile - definitions. Cloud provider definitions now use ``driver`` to refer to the Salt cloud module that - provides the underlying functionality to connect to a cloud host, while cloud profiles continue - to use ``provider`` to refer to provider configurations that you define. - -Cloud Profiles -============== -Set up an initial profile at ``/etc/salt/cloud.profiles``: - -.. code-block:: yaml - - azure-ubuntu: - provider: my-azure-config - image: 'b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-12_04_3-LTS-amd64-server-20131003-en-us-30GB' - size: Small - location: 'East US' - ssh_username: azureuser - ssh_password: verybadpass - slot: production - media_link: 'http://portalvhdabcdefghijklmn.blob.core.windows.net/vhds' - virtual_network_name: azure-virtual-network - subnet_name: azure-subnet - -These options are described in more detail below. Once configured, the profile -can be realized with a salt command: - -.. code-block:: bash - - salt-cloud -p azure-ubuntu newinstance - -This will create an salt minion instance named ``newinstance`` in Azure. If -the command was executed on the salt-master, its Salt key will automatically -be signed on the master. - -Once the instance has been created with salt-minion installed, connectivity to -it can be verified with Salt: - -.. code-block:: bash - - salt newinstance test.version - - -Profile Options -=============== -The following options are currently available for Azure. - -provider --------- -The name of the provider as configured in -`/etc/salt/cloud.providers.d/azure.conf`. - -image ------ -The name of the image to use to create a VM. Available images can be viewed -using the following command: - -.. code-block:: bash - - salt-cloud --list-images my-azure-config - -size ----- -The name of the size to use to create a VM. Available sizes can be viewed using -the following command: - -.. code-block:: bash - - salt-cloud --list-sizes my-azure-config - -location --------- -The name of the location to create a VM in. Available locations can be viewed -using the following command: - -.. code-block:: bash - - salt-cloud --list-locations my-azure-config - -affinity_group --------------- -The name of the affinity group to create a VM in. Either a ``location`` or an -``affinity_group`` may be specified, but not both. See Affinity Groups below. - -ssh_username ------------- -The user to use to log into the newly-created VM to install Salt. - -ssh_password ------------- -The password to use to log into the newly-created VM to install Salt. - -slot ----- -The environment to which the hosted service is deployed. Valid values are -`staging` or `production`. When set to `production`, the resulting URL of the -new VM will be `.cloudapp.net`. When set to `staging`, the resulting -URL will contain a generated hash instead. - -media_link ----------- -This is the URL of the container that will store the disk that this VM uses. -Currently, this container must already exist. If a VM has previously been -created in the associated account, a container should already exist. In the web -interface, go into the Storage area and click one of the available storage -selections. Click the Containers link, and then copy the URL from the container -that will be used. It generally looks like: - -.. code-block:: yaml - - http://portalvhdabcdefghijklmn.blob.core.windows.net/vhds - -service_name ------------- -The name of the service in which to create the VM. If this is not specified, -then a service will be created with the same name as the VM. - -virtual_network_name --------------------- -Optional. The name of the virtual network for the VM to join. If this is not -specified, then no virtual network will be joined. - -subnet_name ------------- -Optional. The name of the subnet in the virtual network for the VM to join. -Requires that a ``virtual_network_name`` is specified. - - -Show Instance -============= -This action is a thin wrapper around ``--full-query``, which displays details on -a single instance only. In an environment with several machines, this will save -a user from having to sort through all instance data, just to examine a single -instance. - -.. code-block:: bash - - salt-cloud -a show_instance myinstance - - -Destroying VMs -============== -There are certain options which can be specified in the global cloud -configuration file (usually ``/etc/salt/cloud``) which affect Salt Cloud's -behavior when a VM is destroyed. - -cleanup_disks -------------- -.. versionadded:: 2015.8.0 - -Default is ``False``. When set to ``True``, Salt Cloud will wait for the VM to -be destroyed, then attempt to destroy the main disk that is associated with the -VM. - -cleanup_vhds ------------- -.. versionadded:: 2015.8.0 - -Default is ``False``. Requires ``cleanup_disks`` to be set to ``True``. When -also set to ``True``, Salt Cloud will ask Azure to delete the VHD associated -with the disk that is also destroyed. - -cleanup_services ----------------- -.. versionadded:: 2015.8.0 - -Default is ``False``. Requires ``cleanup_disks`` to be set to ``True``. When -also set to ``True``, Salt Cloud will wait for the disk to be destroyed, then -attempt to remove the service that is associated with the VM. Because the disk -belongs to the service, the disk must be destroyed before the service can be. - - -Managing Hosted Services -======================== -.. versionadded:: 2015.8.0 - -An account can have one or more hosted services. A hosted service is required -in order to create a VM. However, as mentioned above, if a hosted service is not -specified when a VM is created, then one will automatically be created with the -name of the name. The following functions are also available. - -create_service --------------- -Create a hosted service. The following options are available. - -name -~~~~ -Required. The name of the hosted service to create. - -label -~~~~~ -Required. A label to apply to the hosted service. - -description -~~~~~~~~~~~ -Optional. A longer description of the hosted service. - -location -~~~~~~~~ -Required, if ``affinity_group`` is not set. The location in which to create the -hosted service. Either the ``location`` or the ``affinity_group`` must be set, -but not both. - -affinity_group -~~~~~~~~~~~~~~ -Required, if ``location`` is not set. The affinity group in which to create the -hosted service. Either the ``location`` or the ``affinity_group`` must be set, -but not both. - -extended_properties -~~~~~~~~~~~~~~~~~~~ -Optional. Dictionary containing name/value pairs of hosted service properties. -You can have a maximum of 50 extended property name/value pairs. The maximum -length of the Name element is 64 characters, only alphanumeric characters and -underscores are valid in the Name, and the name must start with a letter. -The value has a maximum length of 255 characters. - -CLI Example -~~~~~~~~~~~ -The following example illustrates creating a hosted service. - -.. code-block:: bash - - salt-cloud -f create_service my-azure name=my-service label=my-service location='West US' - -show_service ------------- -Return details about a specific hosted service. Can also be called with -``get_service``. - -.. code-block:: bash - - salt-cloud -f show_storage my-azure name=my-service - -list_services -------------- -List all hosted services associates with the subscription. - -.. code-block:: bash - - salt-cloud -f list_services my-azure-config - - -delete_service --------------- -Delete a specific hosted service. - -.. code-block:: bash - - salt-cloud -f delete_service my-azure name=my-service - - -Managing Storage Accounts -========================= -.. versionadded:: 2015.8.0 - -Salt Cloud can manage storage accounts associated with the account. The -following functions are available. Deprecated marked as deprecated are marked -as such as per the SDK documentation, but are still included for completeness -with the SDK. - -create_storage --------------- -Create a storage account. The following options are supported. - -name -~~~~ -Required. The name of the storage account to create. - -label -~~~~~ -Required. A label to apply to the storage account. - -description -~~~~~~~~~~~ -Optional. A longer description of the storage account. - -location -~~~~~~~~ -Required, if ``affinity_group`` is not set. The location in which to create the -storage account. Either the ``location`` or the ``affinity_group`` must be set, -but not both. - -affinity_group -~~~~~~~~~~~~~~ -Required, if ``location`` is not set. The affinity group in which to create the -storage account. Either the ``location`` or the ``affinity_group`` must be set, -but not both. - -extended_properties -~~~~~~~~~~~~~~~~~~~ -Optional. Dictionary containing name/value pairs of storage account properties. -You can have a maximum of 50 extended property name/value pairs. The maximum -length of the Name element is 64 characters, only alphanumeric characters and -underscores are valid in the Name, and the name must start with a letter. The -value has a maximum length of 255 characters. - -geo_replication_enabled -~~~~~~~~~~~~~~~~~~~~~~~ -Deprecated. Replaced by the account_type parameter. - -account_type -~~~~~~~~~~~~ -Specifies whether the account supports locally-redundant storage, geo-redundant -storage, zone-redundant storage, or read access geo-redundant storage. Possible -values are: - -- Standard_LRS -- Standard_ZRS -- Standard_GRS -- Standard_RAGRS - -CLI Example -~~~~~~~~~~~ -The following example illustrates creating a storage account. - -.. code-block:: bash - - salt-cloud -f create_storage my-azure name=my-storage label=my-storage location='West US' - -list_storage ------------- -List all storage accounts associates with the subscription. - -.. code-block:: bash - - salt-cloud -f list_storage my-azure-config - -show_storage ------------- -Return details about a specific storage account. Can also be called with -``get_storage``. - -.. code-block:: bash - - salt-cloud -f show_storage my-azure name=my-storage - -update_storage --------------- -Update details concerning a storage account. Any of the options available in -``create_storage`` can be used, but the name cannot be changed. - -.. code-block:: bash - - salt-cloud -f update_storage my-azure name=my-storage label=my-storage - -delete_storage --------------- -Delete a specific storage account. - -.. code-block:: bash - - salt-cloud -f delete_storage my-azure name=my-storage - -show_storage_keys ------------------ -Returns the primary and secondary access keys for the specified storage account. - -.. code-block:: bash - - salt-cloud -f show_storage_keys my-azure name=my-storage - -regenerate_storage_keys ------------------------ -Regenerate storage account keys. Requires a key_type ("primary" or "secondary") -to be specified. - -.. code-block:: bash - - salt-cloud -f regenerate_storage_keys my-azure name=my-storage key_type=primary - - -Managing Disks -============== -.. versionadded:: 2015.8.0 - -When a VM is created, a disk will also be created for it. The following -functions are available for managing disks. Deprecated marked as deprecated are -marked as such as per the SDK documentation, but are still included for -completeness with the SDK. - -show_disk ---------- -Return details about a specific disk. Can also be called with ``get_disk``. - -.. code-block:: bash - - salt-cloud -f show_disk my-azure name=my-disk - -list_disks ----------- -List all disks associates with the account. - -.. code-block:: bash - - salt-cloud -f list_disks my-azure - -update_disk ------------ -Update details for a disk. The following options are available. - -name -~~~~ -Required. The name of the disk to update. - -has_operating_system -~~~~~~~~~~~~~~~~~~~~ -Deprecated. - -label -~~~~~ -Required. The label for the disk. - -media_link -~~~~~~~~~~ -Deprecated. The location of the disk in the account, including the storage -container that it is in. This should not need to be changed. - -new_name -~~~~~~~~ -Deprecated. If renaming the disk, the new name. - -os -~~~ -Deprecated. - -CLI Example -~~~~~~~~~~~ -The following example illustrates updating a disk. - -.. code-block:: bash - - salt-cloud -f update_disk my-azure name=my-disk label=my-disk - -delete_disk ------------ -Delete a specific disk. - -.. code-block:: bash - - salt-cloud -f delete_disk my-azure name=my-disk - - -Managing Service Certificates -============================= -.. versionadded:: 2015.8.0 - -Stored at the cloud service level, these certificates are used by your deployed -services. For more information on service certificates, see the following link: - -* `Manage Certificates`__ - -.. __: https://docs.microsoft.com/en-us/azure/cloud-services/cloud-services-certs-create - -The following functions are available. - -list_service_certificates -------------------------- -List service certificates associated with the account. - -.. code-block:: bash - - salt-cloud -f list_service_certificates my-azure - -show_service_certificate ------------------------- -Show the data for a specific service certificate associated with the account. -The ``name``, ``thumbprint``, and ``thumbalgorithm`` can be obtained from -``list_service_certificates``. Can also be called with -``get_service_certificate``. - -.. code-block:: bash - - salt-cloud -f show_service_certificate my-azure name=my_service_certificate \ - thumbalgorithm=sha1 thumbprint=0123456789ABCDEF - -add_service_certificate ------------------------ -Add a service certificate to the account. This requires that a certificate -already exists, which is then added to the account. For more information on -creating the certificate itself, see: - -* `Create a Service Certificate for Azure`__ - -.. __: https://msdn.microsoft.com/en-us/library/azure/gg432987.aspx - -The following options are available. - -name -~~~~ -Required. The name of the hosted service that the certificate will belong to. - -data -~~~~ -Required. The base-64 encoded form of the pfx file. - -certificate_format -~~~~~~~~~~~~~~~~~~ -Required. The service certificate format. The only supported value is pfx. - -password -~~~~~~~~ -The certificate password. - -.. code-block:: bash - - salt-cloud -f add_service_certificate my-azure name=my-cert \ - data='...CERT_DATA...' certificate_format=pfx password=verybadpass - -delete_service_certificate --------------------------- -Delete a service certificate from the account. The ``name``, ``thumbprint``, -and ``thumbalgorithm`` can be obtained from ``list_service_certificates``. - -.. code-block:: bash - - salt-cloud -f delete_service_certificate my-azure \ - name=my_service_certificate \ - thumbalgorithm=sha1 thumbprint=0123456789ABCDEF - - -Managing Management Certificates -================================ -.. versionadded:: 2015.8.0 - -A Azure management certificate is an X.509 v3 certificate used to authenticate -an agent, such as Visual Studio Tools for Windows Azure or a client application -that uses the Service Management API, acting on behalf of the subscription owner -to manage subscription resources. Azure management certificates are uploaded to -Azure and stored at the subscription level. The management certificate store can -hold up to 100 certificates per subscription. These certificates are used to -authenticate your Windows Azure deployment. - -For more information on management certificates, see the following link. - -* `Manage Certificates`__ - -.. __: https://msdn.microsoft.com/en-us/library/azure/gg981929.aspx - -The following functions are available. - -list_management_certificates ----------------------------- -List management certificates associated with the account. - -.. code-block:: bash - - salt-cloud -f list_management_certificates my-azure - -show_management_certificate ---------------------------- -Show the data for a specific management certificate associated with the account. -The ``name``, ``thumbprint``, and ``thumbalgorithm`` can be obtained from -``list_management_certificates``. Can also be called with -``get_management_certificate``. - -.. code-block:: bash - - salt-cloud -f show_management_certificate my-azure name=my_management_certificate \ - thumbalgorithm=sha1 thumbprint=0123456789ABCDEF - -add_management_certificate --------------------------- -Management certificates must have a key length of at least 2048 bits and should -reside in the Personal certificate store. When the certificate is installed on -the client, it should contain the private key of the certificate. To upload to -the certificate to the Microsoft Azure Management Portal, you must export it as -a .cer format file that does not contain the private key. For more information -on creating management certificates, see the following link: - -* `Create and Upload a Management Certificate for Azure`__ - -.. __: https://docs.microsoft.com/en-us/azure/cloud-services/cloud-services-certs-create - -The following options are available. - -public_key -~~~~~~~~~~ -A base64 representation of the management certificate public key. - -thumbprint -~~~~~~~~~~ -The thumb print that uniquely identifies the management certificate. - -data -~~~~ -The certificate's raw data in base-64 encoded .cer format. - -.. code-block:: bash - - salt-cloud -f add_management_certificate my-azure public_key='...PUBKEY...' \ - thumbprint=0123456789ABCDEF data='...CERT_DATA...' - -delete_management_certificate ------------------------------ -Delete a management certificate from the account. The ``thumbprint`` can be -obtained from ``list_management_certificates``. - -.. code-block:: bash - - salt-cloud -f delete_management_certificate my-azure thumbprint=0123456789ABCDEF - - -Virtual Network Management -========================== -.. versionadded:: 2015.8.0 - -The following are functions for managing virtual networks. - -list_virtual_networks ---------------------- -List input endpoints associated with the deployment. - -.. code-block:: bash - - salt-cloud -f list_virtual_networks my-azure service=myservice deployment=mydeployment - - -Managing Input Endpoints -======================== -.. versionadded:: 2015.8.0 - -Input endpoints are used to manage port access for roles. Because endpoints -cannot be managed by the Azure Python SDK, Salt Cloud uses the API directly. -With versions of Python before 2.7.9, the ``requests-python`` package needs to -be installed in order for this to work. Additionally, the following needs to be -set in the master's configuration file: - -.. code-block:: bash - - backend: requests - -The following functions are available. - -list_input_endpoints --------------------- -List input endpoints associated with the deployment - -.. code-block:: bash - - salt-cloud -f list_input_endpoints my-azure service=myservice deployment=mydeployment - -show_input_endpoint -------------------- -Show an input endpoint associated with the deployment - -.. code-block:: bash - - salt-cloud -f show_input_endpoint my-azure service=myservice \ - deployment=mydeployment name=SSH - -add_input_endpoint ------------------- -Add an input endpoint to the deployment. Please note that there may be a delay -before the changes show up. The following options are available. - -service -~~~~~~~ -Required. The name of the hosted service which the VM belongs to. - -deployment -~~~~~~~~~~ -Required. The name of the deployment that the VM belongs to. If the VM was -created with Salt Cloud, the deployment name probably matches the VM name. - -role -~~~~ -Required. The name of the role that the VM belongs to. If the VM was created -with Salt Cloud, the role name probably matches the VM name. - -name -~~~~ -Required. The name of the input endpoint. This typically matches the port that -the endpoint is set to. For instance, port 22 would be called SSH. - -port -~~~~ -Required. The public (Internet-facing) port that is used for the endpoint. - -local_port -~~~~~~~~~~ -Optional. The private port on the VM itself that will be matched with the port. -This is typically the same as the ``port``. If this value is not specified, it -will be copied from ``port``. - -protocol -~~~~~~~~ -Required. Either ``tcp`` or ``udp``. - -enable_direct_server_return -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Optional. If an internal load balancer exists in the account, it can be used -with a direct server return. The default value is ``False``. Please see the -following article for an explanation of this option. - -* `Load Balancing for Azure Infrastructure Services`__ - -.. __: https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-overview - -timeout_for_tcp_idle_connection -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Optional. The default value is ``4``. Please see the following article for an -explanation of this option. - -* `Configurable Idle Timeout for Azure Load Balancer`__ - -.. __: https://azure.microsoft.com/en-us/blog/new-configurable-idle-timeout-for-azure-load-balancer/ - -CLI Example -~~~~~~~~~~~ -The following example illustrates adding an input endpoint. - -.. code-block:: bash - - salt-cloud -f add_input_endpoint my-azure service=myservice \ - deployment=mydeployment role=myrole name=HTTP local_port=80 \ - port=80 protocol=tcp enable_direct_server_return=False \ - timeout_for_tcp_idle_connection=4 - -update_input_endpoint ---------------------- -Updates the details for a specific input endpoint. All options from -``add_input_endpoint`` are supported. - -.. code-block:: bash - - salt-cloud -f update_input_endpoint my-azure service=myservice \ - deployment=mydeployment role=myrole name=HTTP local_port=80 \ - port=80 protocol=tcp enable_direct_server_return=False \ - timeout_for_tcp_idle_connection=4 - -delete_input_endpoint ---------------------- -Delete an input endpoint from the deployment. Please note that there may be a -delay before the changes show up. The following items are required. - -CLI Example -~~~~~~~~~~~ -The following example illustrates deleting an input endpoint. - -service -~~~~~~~ -The name of the hosted service which the VM belongs to. - -deployment -~~~~~~~~~~ -The name of the deployment that the VM belongs to. If the VM was created with -Salt Cloud, the deployment name probably matches the VM name. - -role -~~~~ -The name of the role that the VM belongs to. If the VM was created with Salt -Cloud, the role name probably matches the VM name. - -name -~~~~ -The name of the input endpoint. This typically matches the port that the -endpoint is set to. For instance, port 22 would be called SSH. - -.. code-block:: bash - - salt-cloud -f delete_input_endpoint my-azure service=myservice \ - deployment=mydeployment role=myrole name=HTTP - - -Managing Affinity Groups -======================== -.. versionadded:: 2015.8.0 - -Affinity groups allow you to group your Azure services to optimize performance. -All services and VMs within an affinity group will be located in the same -region. For more information on Affinity groups, see the following link: - -* `Create an Affinity Group in the Management Portal`__ - -.. __: https://msdn.microsoft.com/en-us/library/azure/jj156209.aspx - -The following functions are available. - -list_affinity_groups --------------------- -List input endpoints associated with the account - -.. code-block:: bash - - salt-cloud -f list_affinity_groups my-azure - -show_affinity_group -------------------- -Show an affinity group associated with the account - -.. code-block:: bash - - salt-cloud -f show_affinity_group my-azure service=myservice \ - deployment=mydeployment name=SSH - -create_affinity_group ---------------------- -Create a new affinity group. The following options are supported. - -name -~~~~ -Required. The name of the new affinity group. - -location -~~~~~~~~ -Required. The region in which the affinity group lives. - -label -~~~~~ -Required. A label describing the new affinity group. - -description -~~~~~~~~~~~ -Optional. A longer description of the affinity group. - -.. code-block:: bash - - salt-cloud -f create_affinity_group my-azure name=my_affinity_group \ - label=my-affinity-group location='West US' - -update_affinity_group ---------------------- -Update an affinity group's properties - -.. code-block:: bash - - salt-cloud -f update_affinity_group my-azure name=my_group label=my_group - -delete_affinity_group ---------------------- -Delete a specific affinity group associated with the account - -.. code-block:: bash - - salt-cloud -f delete_affinity_group my-azure name=my_affinity_group - - -Managing Blob Storage -===================== -.. versionadded:: 2015.8.0 - -Azure storage containers and their contents can be managed with Salt Cloud. This -is not as elegant as using one of the other available clients in Windows, but it -benefits Linux and Unix users, as there are fewer options available on those -platforms. - -Blob Storage Configuration --------------------------- -Blob storage must be configured differently than the standard Azure -configuration. Both a ``storage_account`` and a ``storage_key`` must be -specified either through the Azure provider configuration (in addition to the -other Azure configuration) or via the command line. - -.. code-block:: yaml - - storage_account: mystorage - storage_key: ffhj334fDSGFEGDFGFDewr34fwfsFSDFwe== - -storage_account -~~~~~~~~~~~~~~~ -This is one of the storage accounts that is available via the ``list_storage`` -function. - -storage_key -~~~~~~~~~~~ -Both a primary and a secondary ``storage_key`` can be obtained by running the -``show_storage_keys`` function. Either key may be used. - - -Blob Functions --------------- -The following functions are made available through Salt Cloud for managing -blog storage. - -make_blob_url -~~~~~~~~~~~~~ -Creates the URL to access a blob - -.. code-block:: bash - - salt-cloud -f make_blob_url my-azure container=mycontainer blob=myblob - -container -````````` -Name of the container. - -blob -```` -Name of the blob. - -account -``````` -Name of the storage account. If not specified, derives the host base -from the provider configuration. - -protocol -```````` -Protocol to use: 'http' or 'https'. If not specified, derives the host -base from the provider configuration. - -host_base -````````` -Live host base URL. If not specified, derives the host base from the -provider configuration. - - -list_storage_containers -~~~~~~~~~~~~~~~~~~~~~~~ -List containers associated with the storage account - -.. code-block:: bash - - salt-cloud -f list_storage_containers my-azure - - -create_storage_container -~~~~~~~~~~~~~~~~~~~~~~~~ -Create a storage container - -.. code-block:: bash - - salt-cloud -f create_storage_container my-azure name=mycontainer - -name -```` -Name of container to create. - -meta_name_values -```````````````` -Optional. A dict with name_value pairs to associate with the -container as metadata. Example:{'Category':'test'} - -blob_public_access -`````````````````` -Optional. Possible values include: container, blob - -fail_on_exist -````````````` -Specify whether to throw an exception when the container exists. - - -show_storage_container -~~~~~~~~~~~~~~~~~~~~~~ -Show a container associated with the storage account - -.. code-block:: bash - - salt-cloud -f show_storage_container my-azure name=myservice - -name -```` -Name of container to show. - - -show_storage_container_metadata -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Show a storage container's metadata - -.. code-block:: bash - - salt-cloud -f show_storage_container_metadata my-azure name=myservice - -name -```` -Name of container to show. - -lease_id -```````` -If specified, show_storage_container_metadata only succeeds if the -container's lease is active and matches this ID. - - -set_storage_container_metadata -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Set a storage container's metadata - -.. code-block:: bash - - salt-cloud -f set_storage_container my-azure name=mycontainer \ - x_ms_meta_name_values='{"my_name": "my_value"}' - -name -```` -Name of existing container. -meta_name_values -```````````````` -A dict containing name, value for metadata. -Example: {'category':'test'} -lease_id -```````` -If specified, set_storage_container_metadata only succeeds if the -container's lease is active and matches this ID. - - -show_storage_container_acl -~~~~~~~~~~~~~~~~~~~~~~~~~~ -Show a storage container's acl - -.. code-block:: bash - - salt-cloud -f show_storage_container_acl my-azure name=myservice - -name -```` -Name of existing container. - -lease_id -```````` -If specified, show_storage_container_acl only succeeds if the -container's lease is active and matches this ID. - - -set_storage_container_acl -~~~~~~~~~~~~~~~~~~~~~~~~~ -Set a storage container's acl - -.. code-block:: bash - - salt-cloud -f set_storage_container my-azure name=mycontainer - -name -```` -Name of existing container. - -signed_identifiers -`````````````````` -SignedIdentifiers instance - -blob_public_access -`````````````````` -Optional. Possible values include: container, blob - -lease_id -```````` -If specified, set_storage_container_acl only succeeds if the -container's lease is active and matches this ID. - - -delete_storage_container -~~~~~~~~~~~~~~~~~~~~~~~~ -Delete a container associated with the storage account - -.. code-block:: bash - - salt-cloud -f delete_storage_container my-azure name=mycontainer - -name -```` -Name of container to create. - -fail_not_exist -`````````````` -Specify whether to throw an exception when the container exists. - -lease_id -```````` -If specified, delete_storage_container only succeeds if the -container's lease is active and matches this ID. - - -lease_storage_container -~~~~~~~~~~~~~~~~~~~~~~~ -Lease a container associated with the storage account - -.. code-block:: bash - - salt-cloud -f lease_storage_container my-azure name=mycontainer - -name -```` -Name of container to create. - -lease_action -```````````` -Required. Possible values: acquire|renew|release|break|change - -lease_id -```````` -Required if the container has an active lease. - -lease_duration -`````````````` -Specifies the duration of the lease, in seconds, or negative one -(-1) for a lease that never expires. A non-infinite lease can be -between 15 and 60 seconds. A lease duration cannot be changed -using renew or change. For backwards compatibility, the default is -60, and the value is only used on an acquire operation. - -lease_break_period -`````````````````` -Optional. For a break operation, this is the proposed duration of -seconds that the lease should continue before it is broken, between -0 and 60 seconds. This break period is only used if it is shorter -than the time remaining on the lease. If longer, the time remaining -on the lease is used. A new lease will not be available before the -break period has expired, but the lease may be held for longer than -the break period. If this header does not appear with a break -operation, a fixed-duration lease breaks after the remaining lease -period elapses, and an infinite lease breaks immediately. - -proposed_lease_id -````````````````` -Optional for acquire, required for change. Proposed lease ID, in a -GUID string format. - - -list_blobs -~~~~~~~~~~ -List blobs associated with the container - -.. code-block:: bash - - salt-cloud -f list_blobs my-azure container=mycontainer - -container -````````` -The name of the storage container - -prefix -`````` -Optional. Filters the results to return only blobs whose names -begin with the specified prefix. - -marker -`````` -Optional. A string value that identifies the portion of the list -to be returned with the next list operation. The operation returns -a marker value within the response body if the list returned was -not complete. The marker value may then be used in a subsequent -call to request the next set of list items. The marker value is -opaque to the client. - -maxresults -`````````` -Optional. Specifies the maximum number of blobs to return, -including all BlobPrefix elements. If the request does not specify -maxresults or specifies a value greater than 5,000, the server will -return up to 5,000 items. Setting maxresults to a value less than -or equal to zero results in error response code 400 (Bad Request). - -include -``````` -Optional. Specifies one or more datasets to include in the -response. To specify more than one of these options on the URI, -you must separate each option with a comma. Valid values are:: - - snapshots: - Specifies that snapshots should be included in the - enumeration. Snapshots are listed from oldest to newest in - the response. - metadata: - Specifies that blob metadata be returned in the response. - uncommittedblobs: - Specifies that blobs for which blocks have been uploaded, - but which have not been committed using Put Block List - (REST API), be included in the response. - copy: - Version 2012-02-12 and newer. Specifies that metadata - related to any current or previous Copy Blob operation - should be included in the response. - -delimiter -````````` -Optional. When the request includes this parameter, the operation -returns a BlobPrefix element in the response body that acts as a -placeholder for all blobs whose names begin with the same -substring up to the appearance of the delimiter character. The -delimiter may be a single character or a string. - - -show_blob_service_properties -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Show a blob's service properties - -.. code-block:: bash - - salt-cloud -f show_blob_service_properties my-azure - - -set_blob_service_properties -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Sets the properties of a storage account's Blob service, including -Windows Azure Storage Analytics. You can also use this operation to -set the default request version for all incoming requests that do not -have a version specified. - -.. code-block:: bash - - salt-cloud -f set_blob_service_properties my-azure - -properties -`````````` -a StorageServiceProperties object. - -timeout -``````` -Optional. The timeout parameter is expressed in seconds. - - -show_blob_properties -~~~~~~~~~~~~~~~~~~~~ -Returns all user-defined metadata, standard HTTP properties, and -system properties for the blob. - -.. code-block:: bash - - salt-cloud -f show_blob_properties my-azure container=mycontainer blob=myblob - -container -````````` -Name of existing container. - -blob -```` -Name of existing blob. - -lease_id -```````` -Required if the blob has an active lease. - - -set_blob_properties -~~~~~~~~~~~~~~~~~~~ -Set a blob's properties - -.. code-block:: bash - - salt-cloud -f set_blob_properties my-azure - -container -````````` -Name of existing container. - -blob -```` -Name of existing blob. - -blob_cache_control -`````````````````` -Optional. Modifies the cache control string for the blob. - -blob_content_type -````````````````` -Optional. Sets the blob's content type. - -blob_content_md5 -```````````````` -Optional. Sets the blob's MD5 hash. - -blob_content_encoding -````````````````````` -Optional. Sets the blob's content encoding. - -blob_content_language -````````````````````` -Optional. Sets the blob's content language. - -lease_id -```````` -Required if the blob has an active lease. - -blob_content_disposition -```````````````````````` -Optional. Sets the blob's Content-Disposition header. -The Content-Disposition response header field conveys additional -information about how to process the response payload, and also can -be used to attach additional metadata. For example, if set to -attachment, it indicates that the user-agent should not display the -response, but instead show a Save As dialog with a filename other -than the blob name specified. - - -put_blob -~~~~~~~~ -Upload a blob - -.. code-block:: bash - - salt-cloud -f put_blob my-azure container=base name=top.sls blob_path=/srv/salt/top.sls - salt-cloud -f put_blob my-azure container=base name=content.txt blob_content='Some content' - -container -````````` -Name of existing container. - -name -```` -Name of existing blob. - -blob_path -````````` -The path on the local machine of the file to upload as a blob. Either -this or blob_content must be specified. - -blob_content -```````````` -The actual content to be uploaded as a blob. Either this or blob_path -must me specified. - -cache_control -````````````` -Optional. The Blob service stores this value but does not use or -modify it. - -content_language -```````````````` -Optional. Specifies the natural languages used by this resource. - -content_md5 -``````````` -Optional. An MD5 hash of the blob content. This hash is used to -verify the integrity of the blob during transport. When this header -is specified, the storage service checks the hash that has arrived -with the one that was sent. If the two hashes do not match, the -operation will fail with error code 400 (Bad Request). - -blob_content_type -````````````````` -Optional. Set the blob's content type. - -blob_content_encoding -````````````````````` -Optional. Set the blob's content encoding. - -blob_content_language -````````````````````` -Optional. Set the blob's content language. - -blob_content_md5 -```````````````` -Optional. Set the blob's MD5 hash. - -blob_cache_control -`````````````````` -Optional. Sets the blob's cache control. - -meta_name_values -```````````````` -A dict containing name, value for metadata. - -lease_id -```````` -Required if the blob has an active lease. - - -get_blob -~~~~~~~~ -Download a blob - -.. code-block:: bash - - salt-cloud -f get_blob my-azure container=base name=top.sls local_path=/srv/salt/top.sls - salt-cloud -f get_blob my-azure container=base name=content.txt return_content=True - -container -````````` -Name of existing container. - -name -```` -Name of existing blob. - -local_path -`````````` -The path on the local machine to download the blob to. Either this or -return_content must be specified. - -return_content -`````````````` -Whether or not to return the content directly from the blob. If -specified, must be True or False. Either this or the local_path must -be specified. - -snapshot -```````` -Optional. The snapshot parameter is an opaque DateTime value that, -when present, specifies the blob snapshot to retrieve. - -lease_id -```````` -Required if the blob has an active lease. - -progress_callback -````````````````` -callback for progress with signature function(current, total) where -current is the number of bytes transferred so far, and total is the -size of the blob. - -max_connections -``````````````` -Maximum number of parallel connections to use when the blob size -exceeds 64MB. -Set to 1 to download the blob chunks sequentially. -Set to 2 or more to download the blob chunks in parallel. This uses -more system resources but will download faster. - -max_retries -``````````` -Number of times to retry download of blob chunk if an error occurs. - -retry_wait -`````````` -Sleep time in secs between retries. diff --git a/doc/topics/cloud/azurearm.rst b/doc/topics/cloud/azurearm.rst deleted file mode 100644 index cc9b2122819..00000000000 --- a/doc/topics/cloud/azurearm.rst +++ /dev/null @@ -1,486 +0,0 @@ -============================== -Getting Started With Azure ARM -============================== - -.. versionadded:: 2016.11.0 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -Azure is a cloud service by Microsoft providing virtual machines, SQL services, -media services, and more. Azure ARM (aka, the Azure Resource Manager) is a next -generation version of the Azure portal and API. This document describes how to -use Salt Cloud to create a virtual machine on Azure ARM, with Salt installed. - -More information about Azure is located at `http://www.windowsazure.com/ -`_. - - -Dependencies -============ -* `azure `_ >= 2.0.0rc6 -* `azure-common `_ >= 1.1.4 -* `azure-mgmt `_ >= 0.30.0rc6 -* `azure-mgmt-compute `_ >= 0.33.0 -* `azure-mgmt-network `_ >= 0.30.0rc6 -* `azure-mgmt-resource `_ >= 0.30.0 -* `azure-mgmt-storage `_ >= 0.30.0rc6 -* `azure-mgmt-web `_ >= 0.30.0rc6 -* `azure-storage `_ >= 0.32.0 -* `msrestazure `_ >= 0.4.21 -* A Microsoft Azure account -* `Salt `_ - - -Installation Tips -================= -Because the ``azure`` library requires the ``cryptography`` library, which is -compiled on-the-fly by ``pip``, you may need to install the development tools -for your operating system. - -Before you install ``azure`` with ``pip``, you should make sure that the -required libraries are installed. - -Debian ------- -For Debian and Ubuntu, the following command will ensure that the required -dependencies are installed: - -.. code-block:: bash - - sudo apt-get install build-essential libssl-dev libffi-dev python-dev - -Red Hat -------- -For Fedora and RHEL-derivatives, the following command will ensure that the -required dependencies are installed: - -.. code-block:: bash - - sudo yum install gcc libffi-devel python-devel openssl-devel - - -Configuration -============= - -Set up the provider config at ``/etc/salt/cloud.providers.d/azurearm.conf``: - -.. code-block:: yaml - - # Note: This example is for /etc/salt/cloud.providers.d/azurearm.conf - - my-azurearm-config: - driver: azurearm - master: salt.example.com - subscription_id: 01234567-890a-bcde-f012-34567890abdc - - # https://apps.dev.microsoft.com/#/appList - username: @.onmicrosoft.com - password: verybadpass - location: westus - resource_group: my_rg - - # Optional - network_resource_group: my_net_rg - cleanup_disks: True - cleanup_vhds: True - cleanup_data_disks: True - cleanup_interfaces: True - custom_data: 'This is custom data' - expire_publisher_cache: 604800 # 7 days - expire_offer_cache: 518400 # 6 days - expire_sku_cache: 432000 # 5 days - expire_version_cache: 345600 # 4 days - expire_group_cache: 14400 # 4 hours - expire_interface_cache: 3600 # 1 hour - expire_network_cache: 3600 # 1 hour - -Cloud Profiles -============== -Set up an initial profile at ``/etc/salt/cloud.profiles``: - -.. code-block:: yaml - - azure-ubuntu-pass: - provider: my-azure-config - image: Canonical|UbuntuServer|14.04.5-LTS|14.04.201612050 - size: Standard_D1_v2 - location: eastus - ssh_username: azureuser - ssh_password: verybadpass - - azure-ubuntu-key: - provider: my-azure-config - image: Canonical|UbuntuServer|14.04.5-LTS|14.04.201612050 - size: Standard_D1_v2 - location: eastus - ssh_username: azureuser - ssh_publickeyfile: /path/to/ssh_public_key.pub - - azure-win2012: - provider: my-azure-config - image: MicrosoftWindowsServer|WindowsServer|2012-R2-Datacenter|latest - size: Standard_D1_v2 - location: westus - win_username: azureuser - win_password: verybadpass - -These options are described in more detail below. Once configured, the profile -can be realized with a salt command: - -.. code-block:: bash - - salt-cloud -p azure-ubuntu newinstance - -This will create an salt minion instance named ``newinstance`` in Azure. If -the command was executed on the salt-master, its Salt key will automatically -be signed on the master. - -Once the instance has been created with salt-minion installed, connectivity to -it can be verified with Salt: - -.. code-block:: bash - - salt newinstance test.version - - -Profile Options -=============== -The following options are currently available for Azure ARM. - -provider --------- -The name of the provider as configured in -`/etc/salt/cloud.providers.d/azure.conf`. - -image ------ -Required. The name of the image to use to create a VM. Available images can be -viewed using the following command: - -.. code-block:: bash - - salt-cloud --list-images my-azure-config - -As you will see in ``--list-images``, image names are comprised of the following -fields, separated by the pipe (``|``) character: - -.. code-block:: yaml - - publisher: For example, Canonical or MicrosoftWindowsServer - offer: For example, UbuntuServer or WindowsServer - sku: Such as 14.04.5-LTS or 2012-R2-Datacenter - version: Such as 14.04.201612050 or latest - -It is possible to specify the URL or resource ID path of a custom image that you -have access to, such as: - -.. code-block:: yaml - - https://.blob.core.windows.net/system/Microsoft.Compute/Images//template-osDisk.01234567-890a-bcdef0123-4567890abcde.vhd - -or: - -.. code-block:: yaml - - /subscriptions/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/resourceGroups/myRG/providers/Microsoft.Compute/images/myImage - -size ----- -Required. The name of the size to use to create a VM. Available sizes can be -viewed using the following command: - -.. code-block:: bash - - salt-cloud --list-sizes my-azure-config - -location --------- -Required. The name of the location to create a VM in. Available locations can -be viewed using the following command: - -.. code-block:: bash - - salt-cloud --list-locations my-azure-config - -ssh_username ------------- -Required for Linux. The admin user to add on the instance. It is also used to log -into the newly-created VM to install Salt. - -ssh_keyfile ------------ -Required if using SSH key authentication. The path on the Salt master to the SSH private -key used during the minion bootstrap process. - -ssh_publickeyfile ------------------ -Use either ``ssh_publickeyfile`` or ``ssh_password``. The path on the Salt master to the -SSH public key which will be pushed to the Linux VM. - -ssh_password ------------- -Use either ``ssh_publickeyfile`` or ``ssh_password``. The password for the admin user on -the newly-created Linux virtual machine. - -win_username ------------- -Required for Windows. The user to use to log into the newly-created Windows VM -to install Salt. - -win_password ------------- -Required for Windows. The password to use to log into the newly-created Windows -VM to install Salt. - -win_installer -------------- -Required for Windows. The path to the Salt installer to be uploaded. - -resource_group --------------- -Required. The resource group that all VM resources (VM, network interfaces, -etc) will be created in. - -network_resource_group ----------------------- -Optional. If specified, then the VM will be connected to the virtual network -in this resource group, rather than the parent resource group of the instance. -The VM interfaces and IPs will remain in the configured ``resource_group`` with -the VM. - -network -------- -Required. The virtual network that the VM will be spun up in. - -subnet ------- -Optional. The subnet inside the virtual network that the VM will be spun up in. -Default is ``default``. - -allocate_public_ip ------------------- -Optional. Default is ``False``. If set to ``True``, a public IP will -be created and assigned to the VM. - -load_balancer -------------- -Optional. The load-balancer for the VM's network interface to join. If -specified the backend_pool option need to be set. - -backend_pool ------------- -Optional. Required if the load_balancer option is set. The load-balancer's -Backend Pool the VM's network interface will join. - -iface_name ----------- -Optional. The name to apply to the VM's network interface. If not supplied, the -value will be set to ``-iface0``. - -dns_servers ------------ -Optional. A **list** of the DNS servers to configure for the network interface -(will be set on the VM by the DHCP of the VNET). - -.. code-block:: yaml - - my-azurearm-profile: - provider: azurearm-provider - network: mynetwork - dns_servers: - - 10.1.1.4 - - 10.1.1.5 - -availability_set ----------------- -Optional. If set, the VM will be added to the specified availability set. - -volumes -------- - -Optional. A list of dictionaries describing data disks to attach to the -instance can be specified using this setting. The data disk dictionaries are -passed entirely to the `Azure DataDisk object -`_, -so ad-hoc options can be handled as long as they are valid properties of the -object. - -.. code-block:: yaml - - volumes: - - disk_size_gb: 50 - caching: ReadWrite - - disk_size_gb: 100 - caching: ReadWrite - managed_disk: - storage_account_type: Standard_LRS - -cleanup_disks -------------- -Optional. Default is ``False``. If set to ``True``, disks will be cleaned up -when the VM that they belong to is deleted. - -cleanup_vhds ------------- -Optional. Default is ``False``. If set to ``True``, VHDs will be cleaned up -when the VM and disk that they belong to are deleted. Requires ``cleanup_disks`` -to be set to ``True``. - -cleanup_data_disks ------------------- -Optional. Default is ``False``. If set to ``True``, data disks (non-root -volumes) will be cleaned up whtn the VM that they are attached to is deleted. -Requires ``cleanup_disks`` to be set to ``True``. - -cleanup_interfaces ------------------- -Optional. Default is ``False``. Normally when a VM is deleted, its associated -interfaces and IPs are retained. This is useful if you expect the deleted VM -to be recreated with the same name and network settings. If you would like -interfaces and IPs to be deleted when their associated VM is deleted, set this -to ``True``. - -userdata --------- -Optional. Any custom cloud data that needs to be specified. How this data is -used depends on the operating system and image that is used. For instance, -Linux images that use ``cloud-init`` will import this data for use with that -program. Some Windows images will create a file with a copy of this data, and -others will ignore it. If a Windows image creates a file, then the location -will depend upon the version of Windows. This will be ignored if the -``userdata_file`` is specified. - -userdata_file -------------- -Optional. The path to a file to be read and submitted to Azure as user data. -How this is used depends on the operating system that is being deployed. If -used, any ``userdata`` setting will be ignored. - -userdata_sendkeys ------------------ -Optional. Set to ``True`` in order to generate salt minion keys and provide -them as variables to the userdata script when running it through the template -renderer. The keys can be referenced as ``{{opts['priv_key']}}`` and -``{{opts['pub_key']}}``. - -userdata_template ------------------ -Optional. Enter the renderer, such as ``jinja``, to be used for the userdata -script template. - -wait_for_ip_timeout -------------------- -Optional. Default is ``600``. When waiting for a VM to be created, Salt Cloud -will attempt to connect to the VM's IP address until it starts responding. This -setting specifies the maximum time to wait for a response. - -wait_for_ip_interval --------------------- -Optional. Default is ``10``. How long to wait between attempts to connect to -the VM's IP. - -wait_for_ip_interval_multiplier -------------------------------- -Optional. Default is ``1``. Increase the interval by this multiplier after -each request; helps with throttling. - -expire_publisher_cache ----------------------- -Optional. Default is ``604800``. When fetching image data using -``--list-images``, a number of web calls need to be made to the Azure ARM API. -This is normally very fast when performed using a VM that exists inside Azure -itself, but can be very slow when made from an external connection. - -By default, the publisher data will be cached, and only updated every ``604800`` -seconds (7 days). If you need the publisher cache to be updated at a different -frequency, change this setting. Setting it to ``0`` will turn off the publisher -cache. - -expire_offer_cache ------------------- -Optional. Default is ``518400``. See ``expire_publisher_cache`` for details on -why this exists. - -By default, the offer data will be cached, and only updated every ``518400`` -seconds (6 days). If you need the offer cache to be updated at a different -frequency, change this setting. Setting it to ``0`` will turn off the publiser -cache. - -expire_sku_cache ----------------- -Optional. Default is ``432000``. See ``expire_publisher_cache`` for details on -why this exists. - -By default, the sku data will be cached, and only updated every ``432000`` -seconds (5 days). If you need the sku cache to be updated at a different -frequency, change this setting. Setting it to ``0`` will turn off the sku -cache. - -expire_version_cache --------------------- -Optional. Default is ``345600``. See ``expire_publisher_cache`` for details on -why this exists. - -By default, the version data will be cached, and only updated every ``345600`` -seconds (4 days). If you need the version cache to be updated at a different -frequency, change this setting. Setting it to ``0`` will turn off the version -cache. - -expire_group_cache ------------------- -Optional. Default is ``14400``. See ``expire_publisher_cache`` for details on -why this exists. - -By default, the resource group data will be cached, and only updated every -``14400`` seconds (4 hours). If you need the resource group cache to be updated -at a different frequency, change this setting. Setting it to ``0`` will turn -off the resource group cache. - -expire_interface_cache ----------------------- -Optional. Default is ``3600``. See ``expire_publisher_cache`` for details on -why this exists. - -By default, the interface data will be cached, and only updated every ``3600`` -seconds (1 hour). If you need the interface cache to be updated at a different -frequency, change this setting. Setting it to ``0`` will turn off the interface -cache. - -expire_network_cache --------------------- -Optional. Default is ``3600``. See ``expire_publisher_cache`` for details on -why this exists. - -By default, the network data will be cached, and only updated every ``3600`` -seconds (1 hour). If you need the network cache to be updated at a different -frequency, change this setting. Setting it to ``0`` will turn off the network -cache. - - -Other Options -============= -Other options relevant to Azure ARM. - -storage_account ---------------- -Required for actions involving an Azure storage account. - -storage_key ------------ -Required for actions involving an Azure storage account. - - -Show Instance -============= -This action is a thin wrapper around ``--full-query``, which displays details on -a single instance only. In an environment with several machines, this will save -a user from having to sort through all instance data, just to examine a single -instance. - -.. code-block:: bash - - salt-cloud -a show_instance myinstance diff --git a/salt/cloud/clouds/azurearm.py b/salt/cloud/clouds/azurearm.py deleted file mode 100644 index de93ac18a73..00000000000 --- a/salt/cloud/clouds/azurearm.py +++ /dev/null @@ -1,2043 +0,0 @@ -""" -Azure ARM Cloud Module -====================== - -.. versionadded:: 2016.11.0 - -.. versionchanged:: 2019.2.0 - -The Azure ARM cloud module is used to control access to Microsoft Azure Resource Manager - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -:maintainer: -:depends: - * `azure `_ >= 2.0.0rc6 - * `azure-common `_ >= 1.1.4 - * `azure-mgmt `_ >= 0.30.0rc6 - * `azure-mgmt-compute `_ >= 0.33.0 - * `azure-mgmt-network `_ >= 0.30.0rc6 - * `azure-mgmt-resource `_ >= 0.30.0 - * `azure-mgmt-storage `_ >= 0.30.0rc6 - * `azure-mgmt-web `_ >= 0.30.0rc6 - * `azure-storage `_ >= 0.32.0 - * `msrestazure `_ >= 0.4.21 -:configuration: - Required provider parameters: - - if using username and password: - * ``subscription_id`` - * ``username`` - * ``password`` - - if using a service principal: - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - - if using Managed Service Identity authentication: - * ``subscription_id`` - - Optional provider parameters: - - **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. Possible values: - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` - * HTTP base URL for a custom endpoint, such as Azure Stack. The ``/metadata/endpoints`` path will be added to the URL. - - **userdata** and **userdata_file**: - Azure Resource Manager uses a separate VirtualMachineExtension object to pass userdata scripts to the virtual - machine. Arbitrary shell commands can be passed via the ``userdata`` parameter, or via a file local to the Salt - Cloud system using the ``userdata_file`` parameter. Note that the local file is not treated as a script by the - extension, so "one-liners" probably work best. If greater functionality is desired, a web-hosted script file can - be specified via ``userdata_file: https://raw.githubusercontent.com/account/repo/master/azure-script.py``, which - will be executed on the system after VM creation. For Windows systems, script files ending in ``.ps1`` will be - executed with ``powershell.exe``. The ``userdata`` parameter takes precedence over the ``userdata_file`` parameter - when creating the custom script extension. - - **win_installer**: - This parameter, which holds the local path to the Salt Minion installer package, is used to determine if the - virtual machine type will be "Windows". Only set this parameter on profiles which install Windows operating systems. - - -Example ``/etc/salt/cloud.providers`` or -``/etc/salt/cloud.providers.d/azure.conf`` configuration: - -.. code-block:: yaml - - my-azure-config with username and password: - driver: azurearm - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - username: larry - password: 123pass - - Or my-azure-config with service principal: - driver: azurearm - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - tenant: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - client_id: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - secret: XXXXXXXXXXXXXXXXXXXXXXXX - cloud_environment: AZURE_US_GOV_CLOUD - - The Service Principal can be created with the new Azure CLI (https://github.com/Azure/azure-cli) with: - az ad sp create-for-rbac -n "http://" --role --scopes - For example, this creates a service principal with 'owner' role for the whole subscription: - az ad sp create-for-rbac -n "http://mysaltapp" --role owner --scopes /subscriptions/3287abc8-f98a-c678-3bde-326766fd3617 - - *Note: review the details of Service Principals. Owner role is more than you normally need, and you can restrict - scope to a resource group or individual resources. -""" - -import importlib -import logging -import os -import os.path -import pprint -import string -import time -from functools import wraps -from multiprocessing import cpu_count -from multiprocessing.pool import ThreadPool - -import salt.cache -import salt.config as config -import salt.loader -import salt.utils.azurearm -import salt.utils.cloud -import salt.utils.files -import salt.utils.stringutils -import salt.utils.yaml -import salt.version -from salt.exceptions import ( - SaltCloudConfigError, - SaltCloudExecutionFailure, - SaltCloudExecutionTimeout, - SaltCloudSystemExit, -) - -HAS_LIBS = False -try: - import azure.mgmt.compute.models as compute_models - import azure.mgmt.network.models as network_models - from azure.storage.blob.blockblobservice import BlockBlobService - from msrestazure.azure_exceptions import CloudError - - HAS_LIBS = True -except ImportError: - pass - -__virtualname__ = "azurearm" - -log = logging.getLogger(__name__) - - -def __virtual__(): - """ - Check for Azure configurations. - """ - if get_configured_provider() is False: - return False - - if get_dependencies() is False: - return ( - False, - "The following dependencies are required to use the AzureARM driver: " - "Microsoft Azure SDK for Python >= 2.0rc6, " - "Microsoft Azure Storage SDK for Python >= 0.32, " - "MS REST Azure (msrestazure) >= 0.4", - ) - - return __virtualname__ - - -def _get_active_provider_name(): - try: - return __active_provider_name__.value() - except AttributeError: - return __active_provider_name__ - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about msazure deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "This cloud provider will be removed from Salt in version 3007 due to " - "the deprecation of the 'Classic' API for Azure. Please migrate to " - "Azure Resource Manager by March 1, 2023 " - "(https://docs.microsoft.com/en-us/azure/virtual-machines/classic-vm-deprecation)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -@_deprecation_message -def get_api_versions(call=None, kwargs=None): # pylint: disable=unused-argument - """ - Get a resource type api versions - """ - if kwargs is None: - kwargs = {} - - if "resource_provider" not in kwargs: - raise SaltCloudSystemExit("A resource_provider must be specified") - - if "resource_type" not in kwargs: - raise SaltCloudSystemExit("A resource_type must be specified") - - api_versions = [] - - try: - resconn = get_conn(client_type="resource") - provider_query = resconn.providers.get( - resource_provider_namespace=kwargs["resource_provider"] - ) - - for resource in provider_query.resource_types: - if str(resource.resource_type) == kwargs["resource_type"]: - resource_dict = resource.as_dict() - api_versions = resource_dict["api_versions"] - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("resource", exc.message) - - return api_versions - - -@_deprecation_message -def get_resource_by_id(resource_id, api_version, extract_value=None): - """ - Get an AzureARM resource by id - """ - ret = {} - - try: - resconn = get_conn(client_type="resource") - resource_query = resconn.resources.get_by_id( - resource_id=resource_id, api_version=api_version - ) - resource_dict = resource_query.as_dict() - if extract_value is not None: - ret = resource_dict[extract_value] - else: - ret = resource_dict - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("resource", exc.message) - ret = {"Error": exc.message} - - return ret - - -def get_configured_provider(): - """ - Return the first configured provider instance. - """ - key_combos = [ - ("subscription_id", "tenant", "client_id", "secret"), - ("subscription_id", "username", "password"), - ("subscription_id",), - ] - - for combo in key_combos: - provider = config.is_provider_configured( - __opts__, - _get_active_provider_name() or __virtualname__, - combo, - ) - - if provider: - return provider - - return provider - - -@_deprecation_message -def get_dependencies(): - """ - Warn if dependencies aren't met. - """ - return config.check_driver_dependencies(__virtualname__, {"azurearm": HAS_LIBS}) - - -@_deprecation_message -def get_conn(client_type): - """ - Return a connection object for a client type. - """ - conn_kwargs = {} - - conn_kwargs["subscription_id"] = salt.utils.stringutils.to_str( - config.get_cloud_config_value( - "subscription_id", get_configured_provider(), __opts__, search_global=False - ) - ) - - cloud_env = config.get_cloud_config_value( - "cloud_environment", get_configured_provider(), __opts__, search_global=False - ) - - if cloud_env is not None: - conn_kwargs["cloud_environment"] = cloud_env - - tenant = config.get_cloud_config_value( - "tenant", get_configured_provider(), __opts__, search_global=False - ) - - if tenant is not None: - client_id = config.get_cloud_config_value( - "client_id", get_configured_provider(), __opts__, search_global=False - ) - secret = config.get_cloud_config_value( - "secret", get_configured_provider(), __opts__, search_global=False - ) - conn_kwargs.update({"client_id": client_id, "secret": secret, "tenant": tenant}) - - username = config.get_cloud_config_value( - "username", get_configured_provider(), __opts__, search_global=False - ) - - if username: - password = config.get_cloud_config_value( - "password", get_configured_provider(), __opts__, search_global=False - ) - conn_kwargs.update({"username": username, "password": password}) - - client = salt.utils.azurearm.get_client(client_type=client_type, **conn_kwargs) - - return client - - -@_deprecation_message -def get_location(call=None, kwargs=None): # pylint: disable=unused-argument - """ - Return the location that is configured for this provider - """ - if not kwargs: - kwargs = {} - vm_dict = get_configured_provider() - vm_dict.update(kwargs) - return config.get_cloud_config_value( - "location", vm_dict, __opts__, search_global=False - ) - - -@_deprecation_message -def avail_locations(call=None): - """ - Return a dict of all available regions. - """ - if call == "action": - raise SaltCloudSystemExit( - "The avail_locations function must be called with " - "-f or --function, or with the --list-locations option" - ) - - ret = {} - ret["locations"] = [] - - try: - resconn = get_conn(client_type="resource") - provider_query = resconn.providers.get( - resource_provider_namespace="Microsoft.Compute" - ) - locations = [] - for resource in provider_query.resource_types: - if str(resource.resource_type) == "virtualMachines": - resource_dict = resource.as_dict() - locations = resource_dict["locations"] - for location in locations: - lowercase = location.lower().replace(" ", "") - ret["locations"].append(lowercase) - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("resource", exc.message) - ret = {"Error": exc.message} - - return ret - - -@_deprecation_message -def avail_images(call=None): - """ - Return a dict of all available images on the provider - """ - if call == "action": - raise SaltCloudSystemExit( - "The avail_images function must be called with " - "-f or --function, or with the --list-images option" - ) - compconn = get_conn(client_type="compute") - region = get_location() - publishers = [] - ret = {} - - def _get_publisher_images(publisher): - """ - Get all images from a specific publisher - """ - data = {} - try: - offers = compconn.virtual_machine_images.list_offers( - location=region, - publisher_name=publisher, - ) - for offer_obj in offers: - offer = offer_obj.as_dict() - skus = compconn.virtual_machine_images.list_skus( - location=region, - publisher_name=publisher, - offer=offer["name"], - ) - for sku_obj in skus: - sku = sku_obj.as_dict() - results = compconn.virtual_machine_images.list( - location=region, - publisher_name=publisher, - offer=offer["name"], - skus=sku["name"], - ) - for version_obj in results: - version = version_obj.as_dict() - name = "|".join( - ( - publisher, - offer["name"], - sku["name"], - version["name"], - ) - ) - data[name] = { - "publisher": publisher, - "offer": offer["name"], - "sku": sku["name"], - "version": version["name"], - } - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("compute", exc.message) - data = {publisher: exc.message} - - return data - - try: - publishers_query = compconn.virtual_machine_images.list_publishers( - location=region - ) - for publisher_obj in publishers_query: - publisher = publisher_obj.as_dict() - publishers.append(publisher["name"]) - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("compute", exc.message) - - pool = ThreadPool(cpu_count() * 6) - results = pool.map_async(_get_publisher_images, publishers) - results.wait() - - ret = {k: v for result in results.get() for k, v in result.items()} - - return ret - - -@_deprecation_message -def avail_sizes(call=None): - """ - Return a list of sizes available from the provider - """ - if call == "action": - raise SaltCloudSystemExit( - "The avail_sizes function must be called with " - "-f or --function, or with the --list-sizes option" - ) - - compconn = get_conn(client_type="compute") - - ret = {} - location = get_location() - - try: - sizes = compconn.virtual_machine_sizes.list(location=location) - for size_obj in sizes: - size = size_obj.as_dict() - ret[size["name"]] = size - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("compute", exc.message) - ret = {"Error": exc.message} - - return ret - - -@_deprecation_message -def list_nodes(call=None): - """ - List VMs on this Azure account - """ - if call == "action": - raise SaltCloudSystemExit( - "The list_nodes function must be called with -f or --function." - ) - - ret = {} - - nodes = list_nodes_full() - for node in nodes: - ret[node] = {"name": node} - for prop in ("id", "image", "size", "state", "private_ips", "public_ips"): - ret[node][prop] = nodes[node].get(prop) - return ret - - -@_deprecation_message -def list_nodes_full(call=None): - """ - List all VMs on the subscription with full information - """ - if call == "action": - raise SaltCloudSystemExit( - "The list_nodes_full function must be called with -f or --function." - ) - - netapi_versions = get_api_versions( - kwargs={ - "resource_provider": "Microsoft.Network", - "resource_type": "networkInterfaces", - } - ) - netapi_version = netapi_versions[0] - compconn = get_conn(client_type="compute") - - ret = {} - - def _get_node_info(node): - """ - Get node info. - """ - node_ret = {} - node["id"] = node["vm_id"] - node["size"] = node["hardware_profile"]["vm_size"] - node["state"] = node["provisioning_state"] - node["public_ips"] = [] - node["private_ips"] = [] - node_ret[node["name"]] = node - try: - image_ref = node["storage_profile"]["image_reference"] - node["image"] = "|".join( - [ - image_ref["publisher"], - image_ref["offer"], - image_ref["sku"], - image_ref["version"], - ] - ) - except (TypeError, KeyError): - try: - node["image"] = node["storage_profile"]["os_disk"]["image"]["uri"] - except (TypeError, KeyError): - node["image"] = ( - node.get("storage_profile", {}).get("image_reference", {}).get("id") - ) - try: - netifaces = node["network_profile"]["network_interfaces"] - for index, netiface in enumerate(netifaces): - netiface_name = get_resource_by_id( - netiface["id"], netapi_version, "name" - ) - netiface, pubips, privips = _get_network_interface( - netiface_name, node["resource_group"] - ) - node["network_profile"]["network_interfaces"][index].update(netiface) - node["public_ips"].extend(pubips) - node["private_ips"].extend(privips) - except Exception: # pylint: disable=broad-except - pass - - node_ret[node["name"]] = node - - return node_ret - - for group in list_resource_groups(): - nodes = [] - nodes_query = compconn.virtual_machines.list(resource_group_name=group) - for node_obj in nodes_query: - node = node_obj.as_dict() - node["resource_group"] = group - nodes.append(node) - - pool = ThreadPool(cpu_count() * 6) - results = pool.map_async(_get_node_info, nodes) - results.wait() - - group_ret = {k: v for result in results.get() for k, v in result.items()} - ret.update(group_ret) - - return ret - - -@_deprecation_message -def list_resource_groups(call=None): - """ - List resource groups associated with the subscription - """ - if call == "action": - raise SaltCloudSystemExit( - "The list_hosted_services function must be called with -f or --function" - ) - - resconn = get_conn(client_type="resource") - ret = {} - try: - groups = resconn.resource_groups.list() - - for group_obj in groups: - group = group_obj.as_dict() - ret[group["name"]] = group - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("resource", exc.message) - ret = {"Error": exc.message} - - return ret - - -@_deprecation_message -def show_instance(name, call=None): - """ - Show the details from AzureARM concerning an instance - """ - if call != "action": - raise SaltCloudSystemExit( - "The show_instance action must be called with -a or --action." - ) - try: - node = list_nodes_full("function")[name] - except KeyError: - log.debug("Failed to get data for node '%s'", name) - node = {} - - __utils__["cloud.cache_node"](node, _get_active_provider_name(), __opts__) - - return node - - -@_deprecation_message -def delete_interface(call=None, kwargs=None): # pylint: disable=unused-argument - """ - Delete a network interface. - """ - if kwargs is None: - kwargs = {} - - netconn = get_conn(client_type="network") - - if kwargs.get("resource_group") is None: - kwargs["resource_group"] = config.get_cloud_config_value( - "resource_group", {}, __opts__, search_global=True - ) - - ips = [] - iface = netconn.network_interfaces.get( - kwargs["resource_group"], - kwargs["iface_name"], - ) - iface_name = iface.name - for ip_ in iface.ip_configurations: - ips.append(ip_.name) - - poller = netconn.network_interfaces.delete( - kwargs["resource_group"], - kwargs["iface_name"], - ) - poller.wait() - - for ip_ in ips: - poller = netconn.public_ip_addresses.delete(kwargs["resource_group"], ip_) - poller.wait() - - return {iface_name: ips} - - -def _get_public_ip(name, resource_group): - """ - Get the public ip address details by name. - """ - netconn = get_conn(client_type="network") - try: - pubip_query = netconn.public_ip_addresses.get( - resource_group_name=resource_group, public_ip_address_name=name - ) - pubip = pubip_query.as_dict() - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("network", exc.message) - pubip = {"error": exc.message} - - return pubip - - -def _get_network_interface(name, resource_group): - """ - Get a network interface. - """ - public_ips = [] - private_ips = [] - netapi_versions = get_api_versions( - kwargs={ - "resource_provider": "Microsoft.Network", - "resource_type": "publicIPAddresses", - } - ) - netapi_version = netapi_versions[0] - netconn = get_conn(client_type="network") - netiface_query = netconn.network_interfaces.get( - resource_group_name=resource_group, network_interface_name=name - ) - - netiface = netiface_query.as_dict() - for index, ip_config in enumerate(netiface["ip_configurations"]): - if ip_config.get("private_ip_address") is not None: - private_ips.append(ip_config["private_ip_address"]) - if "id" in ip_config.get("public_ip_address", {}): - public_ip_name = get_resource_by_id( - ip_config["public_ip_address"]["id"], netapi_version, "name" - ) - public_ip = _get_public_ip(public_ip_name, resource_group) - public_ips.append(public_ip["ip_address"]) - netiface["ip_configurations"][index]["public_ip_address"].update(public_ip) - - return netiface, public_ips, private_ips - - -@_deprecation_message -def create_network_interface(call=None, kwargs=None): - """ - Create a network interface. - """ - if call != "action": - raise SaltCloudSystemExit( - "The create_network_interface action must be called with -a or --action." - ) - - # pylint: disable=invalid-name - IPAllocationMethod = getattr(network_models, "IPAllocationMethod") - # pylint: disable=invalid-name - NetworkInterface = getattr(network_models, "NetworkInterface") - # pylint: disable=invalid-name - NetworkInterfaceIPConfiguration = getattr( - network_models, "NetworkInterfaceIPConfiguration" - ) - # pylint: disable=invalid-name - PublicIPAddress = getattr(network_models, "PublicIPAddress") - - if not isinstance(kwargs, dict): - kwargs = {} - - vm_ = kwargs - netconn = get_conn(client_type="network") - - if kwargs.get("location") is None: - kwargs["location"] = get_location() - - if kwargs.get("network") is None: - kwargs["network"] = config.get_cloud_config_value( - "network", vm_, __opts__, search_global=False - ) - - if kwargs.get("subnet") is None: - kwargs["subnet"] = config.get_cloud_config_value( - "subnet", vm_, __opts__, search_global=False - ) - - if kwargs.get("network_resource_group") is None: - kwargs["network_resource_group"] = config.get_cloud_config_value( - "resource_group", vm_, __opts__, search_global=False - ) - - if kwargs.get("iface_name") is None: - kwargs["iface_name"] = "{}-iface0".format(vm_["name"]) - - try: - subnet_obj = netconn.subnets.get( - resource_group_name=kwargs["network_resource_group"], - virtual_network_name=kwargs["network"], - subnet_name=kwargs["subnet"], - ) - except CloudError as exc: - raise SaltCloudSystemExit( - '{} (Resource Group: "{}", VNET: "{}", Subnet: "{}")'.format( - exc.message, - kwargs["network_resource_group"], - kwargs["network"], - kwargs["subnet"], - ) - ) - - ip_kwargs = {} - ip_configurations = None - - if "load_balancer_backend_address_pools" in kwargs: - pool_dicts = kwargs["load_balancer_backend_address_pools"] - if isinstance(pool_dicts, dict): - pool_ids = [] - for load_bal, be_pools in pool_dicts.items(): - for pool in be_pools: - try: - lbbep_data = netconn.load_balancer_backend_address_pools.get( - kwargs["resource_group"], - load_bal, - pool, - ) - pool_ids.append({"id": lbbep_data.as_dict()["id"]}) - except CloudError as exc: - log.error("There was a cloud error: %s", str(exc)) - except KeyError as exc: - log.error( - "There was an error getting the Backend Pool ID: %s", - str(exc), - ) - ip_kwargs["load_balancer_backend_address_pools"] = pool_ids - - if "private_ip_address" in kwargs.keys(): - ip_kwargs["private_ip_address"] = kwargs["private_ip_address"] - ip_kwargs["private_ip_allocation_method"] = IPAllocationMethod.static - else: - ip_kwargs["private_ip_allocation_method"] = IPAllocationMethod.dynamic - - if kwargs.get("allocate_public_ip") is True: - pub_ip_name = "{}-ip".format(kwargs["iface_name"]) - poller = netconn.public_ip_addresses.create_or_update( - resource_group_name=kwargs["resource_group"], - public_ip_address_name=pub_ip_name, - parameters=PublicIPAddress( - location=kwargs["location"], - public_ip_allocation_method=IPAllocationMethod.static, - ), - ) - count = 0 - poller.wait() - while True: - try: - pub_ip_data = netconn.public_ip_addresses.get( - kwargs["resource_group"], - pub_ip_name, - ) - if pub_ip_data.ip_address: # pylint: disable=no-member - ip_kwargs["public_ip_address"] = PublicIPAddress( - id=str(pub_ip_data.id), # pylint: disable=no-member - ) - ip_configurations = [ - NetworkInterfaceIPConfiguration( - name="{}-ip".format(kwargs["iface_name"]), - subnet=subnet_obj, - **ip_kwargs - ) - ] - break - except CloudError as exc: - log.error("There was a cloud error: %s", exc) - count += 1 - if count > 120: - raise ValueError("Timed out waiting for public IP Address.") - time.sleep(5) - else: - priv_ip_name = "{}-ip".format(kwargs["iface_name"]) - ip_configurations = [ - NetworkInterfaceIPConfiguration( - name=priv_ip_name, subnet=subnet_obj, **ip_kwargs - ) - ] - - network_security_group = None - if kwargs.get("security_group") is not None: - network_security_group = netconn.network_security_groups.get( - resource_group_name=kwargs["resource_group"], - network_security_group_name=kwargs["security_group"], - ) - - iface_params = NetworkInterface( - location=kwargs["location"], - network_security_group=network_security_group, - ip_configurations=ip_configurations, - ) - - poller = netconn.network_interfaces.create_or_update( - kwargs["resource_group"], kwargs["iface_name"], iface_params - ) - try: - poller.wait() - except Exception as exc: # pylint: disable=broad-except - log.warning( - "Network interface creation could not be polled. " - "It is likely that we are reusing an existing interface. (%s)", - exc, - ) - - count = 0 - while True: - try: - return _get_network_interface( - kwargs["iface_name"], kwargs["resource_group"] - ) - except CloudError: - count += 1 - if count > 120: - raise ValueError("Timed out waiting for operation to complete.") - time.sleep(5) - - -def request_instance(vm_, kwargs=None): - """ - Request a VM from Azure. - """ - compconn = get_conn(client_type="compute") - - # pylint: disable=invalid-name - CachingTypes = getattr(compute_models, "CachingTypes") - # pylint: disable=invalid-name - DataDisk = getattr(compute_models, "DataDisk") - # pylint: disable=invalid-name - DiskCreateOptionTypes = getattr(compute_models, "DiskCreateOptionTypes") - # pylint: disable=invalid-name - HardwareProfile = getattr(compute_models, "HardwareProfile") - # pylint: disable=invalid-name - ImageReference = getattr(compute_models, "ImageReference") - # pylint: disable=invalid-name - LinuxConfiguration = getattr(compute_models, "LinuxConfiguration") - # pylint: disable=invalid-name - SshConfiguration = getattr(compute_models, "SshConfiguration") - # pylint: disable=invalid-name - SshPublicKey = getattr(compute_models, "SshPublicKey") - # pylint: disable=invalid-name - NetworkInterfaceReference = getattr(compute_models, "NetworkInterfaceReference") - # pylint: disable=invalid-name - NetworkProfile = getattr(compute_models, "NetworkProfile") - # pylint: disable=invalid-name - OSDisk = getattr(compute_models, "OSDisk") - # pylint: disable=invalid-name - OSProfile = getattr(compute_models, "OSProfile") - # pylint: disable=invalid-name - StorageProfile = getattr(compute_models, "StorageProfile") - # pylint: disable=invalid-name - VirtualHardDisk = getattr(compute_models, "VirtualHardDisk") - # pylint: disable=invalid-name - VirtualMachine = getattr(compute_models, "VirtualMachine") - # pylint: disable=invalid-name - VirtualMachineSizeTypes = getattr(compute_models, "VirtualMachineSizeTypes") - - subscription_id = config.get_cloud_config_value( - "subscription_id", get_configured_provider(), __opts__, search_global=False - ) - - if vm_.get("driver") is None: - vm_["driver"] = "azurearm" - - if vm_.get("location") is None: - vm_["location"] = get_location() - - if vm_.get("resource_group") is None: - vm_["resource_group"] = config.get_cloud_config_value( - "resource_group", vm_, __opts__, search_global=True - ) - - if vm_.get("name") is None: - vm_["name"] = config.get_cloud_config_value( - "name", vm_, __opts__, search_global=True - ) - - # pylint: disable=unused-variable - iface_data, public_ips, private_ips = create_network_interface( - call="action", kwargs=vm_ - ) - vm_["iface_id"] = iface_data["id"] - - disk_name = "{}-vol0".format(vm_["name"]) - - vm_username = config.get_cloud_config_value( - "ssh_username", - vm_, - __opts__, - search_global=True, - default=config.get_cloud_config_value( - "win_username", vm_, __opts__, search_global=True - ), - ) - - ssh_publickeyfile_contents = None - ssh_publickeyfile = config.get_cloud_config_value( - "ssh_publickeyfile", vm_, __opts__, search_global=False, default=None - ) - if ssh_publickeyfile is not None: - try: - with salt.utils.files.fopen(ssh_publickeyfile, "r") as spkc_: - ssh_publickeyfile_contents = spkc_.read() - except Exception as exc: # pylint: disable=broad-except - raise SaltCloudConfigError( - "Failed to read ssh publickey file '{}': {}".format( - ssh_publickeyfile, exc.args[-1] - ) - ) - - disable_password_authentication = config.get_cloud_config_value( - "disable_password_authentication", - vm_, - __opts__, - search_global=False, - default=False, - ) - - os_kwargs = {} - win_installer = config.get_cloud_config_value( - "win_installer", vm_, __opts__, search_global=True - ) - if not win_installer and ssh_publickeyfile_contents is not None: - sshpublickey = SshPublicKey( - key_data=ssh_publickeyfile_contents, - path="/home/{}/.ssh/authorized_keys".format(vm_username), - ) - sshconfiguration = SshConfiguration( - public_keys=[sshpublickey], - ) - linuxconfiguration = LinuxConfiguration( - disable_password_authentication=disable_password_authentication, - ssh=sshconfiguration, - ) - os_kwargs["linux_configuration"] = linuxconfiguration - vm_password = None - else: - vm_password = salt.utils.stringutils.to_str( - config.get_cloud_config_value( - "ssh_password", - vm_, - __opts__, - search_global=True, - default=config.get_cloud_config_value( - "win_password", vm_, __opts__, search_global=True - ), - ) - ) - - if win_installer or ( - vm_password is not None and not disable_password_authentication - ): - if not isinstance(vm_password, str): - raise SaltCloudSystemExit("The admin password must be a string.") - if len(vm_password) < 8 or len(vm_password) > 123: - raise SaltCloudSystemExit( - "The admin password must be between 8-123 characters long." - ) - complexity = 0 - if any(char.isdigit() for char in vm_password): - complexity += 1 - if any(char.isupper() for char in vm_password): - complexity += 1 - if any(char.islower() for char in vm_password): - complexity += 1 - if any(char in string.punctuation for char in vm_password): - complexity += 1 - if complexity < 3: - raise SaltCloudSystemExit( - "The admin password must contain at least 3 of the following types: " - "upper, lower, digits, special characters" - ) - os_kwargs["admin_password"] = vm_password - - availability_set = config.get_cloud_config_value( - "availability_set", vm_, __opts__, search_global=False, default=None - ) - if availability_set is not None and isinstance(availability_set, str): - availability_set = { - "id": "/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/availabilitySets/{}".format( - subscription_id, vm_["resource_group"], availability_set - ) - } - else: - availability_set = None - - cloud_env = _get_cloud_environment() - - storage_endpoint_suffix = cloud_env.suffixes.storage_endpoint - - if isinstance(vm_.get("volumes"), str): - volumes = salt.utils.yaml.safe_load(vm_["volumes"]) - else: - volumes = vm_.get("volumes") - - data_disks = None - if isinstance(volumes, list): - data_disks = [] - else: - volumes = [] - - lun = 0 - luns = [] - for volume in volumes: - if isinstance(volume, str): - volume = {"name": volume} - - volume.setdefault( - "name", - volume.get( - "name", - volume.get("name", "{}-datadisk{}".format(vm_["name"], str(lun))), - ), - ) - - volume.setdefault( - "disk_size_gb", - volume.get("logical_disk_size_in_gb", volume.get("size", 100)), - ) - # Old kwarg was host_caching, new name is caching - volume.setdefault("caching", volume.get("host_caching", "ReadOnly")) - while lun in luns: - lun += 1 - if lun > 15: - log.error("Maximum lun count has been reached") - break - volume.setdefault("lun", lun) - lun += 1 - # The default vhd is {vm_name}-datadisk{lun}.vhd - if "media_link" in volume: - volume["vhd"] = VirtualHardDisk(uri=volume["media_link"]) - del volume["media_link"] - elif volume.get("vhd") == "unmanaged": - volume["vhd"] = VirtualHardDisk( - uri="https://{}.blob.{}/vhds/{}-datadisk{}.vhd".format( - vm_["storage_account"], - storage_endpoint_suffix, - vm_["name"], - volume["lun"], - ), - ) - elif "vhd" in volume: - volume["vhd"] = VirtualHardDisk(uri=volume["vhd"]) - - if "image" in volume: - volume["create_option"] = "from_image" - elif "attach" in volume: - volume["create_option"] = "attach" - else: - volume["create_option"] = "empty" - data_disks.append(DataDisk(**volume)) - - img_ref = None - if vm_["image"].startswith("http") or vm_.get("vhd") == "unmanaged": - if vm_["image"].startswith("http"): - source_image = VirtualHardDisk(uri=vm_["image"]) - else: - source_image = None - if "|" in vm_["image"]: - img_pub, img_off, img_sku, img_ver = vm_["image"].split("|") - img_ref = ImageReference( - publisher=img_pub, - offer=img_off, - sku=img_sku, - version=img_ver, - ) - elif vm_["image"].startswith("/subscriptions"): - img_ref = ImageReference(id=vm_["image"]) - if win_installer: - os_type = "Windows" - else: - os_type = "Linux" - os_disk = OSDisk( - caching=CachingTypes.none, - create_option=DiskCreateOptionTypes.from_image, - name=disk_name, - vhd=VirtualHardDisk( - uri="https://{}.blob.{}/vhds/{}.vhd".format( - vm_["storage_account"], - storage_endpoint_suffix, - disk_name, - ), - ), - os_type=os_type, - image=source_image, - disk_size_gb=vm_.get("os_disk_size_gb"), - ) - else: - source_image = None - os_type = None - os_disk = OSDisk( - create_option=DiskCreateOptionTypes.from_image, - disk_size_gb=vm_.get("os_disk_size_gb"), - ) - if "|" in vm_["image"]: - img_pub, img_off, img_sku, img_ver = vm_["image"].split("|") - img_ref = ImageReference( - publisher=img_pub, - offer=img_off, - sku=img_sku, - version=img_ver, - ) - elif vm_["image"].startswith("/subscriptions"): - img_ref = ImageReference(id=vm_["image"]) - - userdata_file = config.get_cloud_config_value( - "userdata_file", vm_, __opts__, search_global=False, default=None - ) - userdata = config.get_cloud_config_value( - "userdata", vm_, __opts__, search_global=False, default=None - ) - userdata_template = config.get_cloud_config_value( - "userdata_template", vm_, __opts__, search_global=False, default=None - ) - - if userdata_file: - if os.path.exists(userdata_file): - with salt.utils.files.fopen(userdata_file, "r") as fh_: - userdata = fh_.read() - - if userdata and userdata_template: - userdata_sendkeys = config.get_cloud_config_value( - "userdata_sendkeys", vm_, __opts__, search_global=False, default=None - ) - if userdata_sendkeys: - vm_["priv_key"], vm_["pub_key"] = salt.utils.cloud.gen_keys( - config.get_cloud_config_value("keysize", vm_, __opts__) - ) - - key_id = vm_.get("name") - if "append_domain" in vm_: - key_id = ".".join([key_id, vm_["append_domain"]]) - - salt.utils.cloud.accept_key(__opts__["pki_dir"], vm_["pub_key"], key_id) - - userdata = salt.utils.cloud.userdata_template(__opts__, vm_, userdata) - - custom_extension = None - if userdata is not None or userdata_file is not None: - try: - if win_installer: - publisher = "Microsoft.Compute" - virtual_machine_extension_type = "CustomScriptExtension" - type_handler_version = "1.8" - if userdata_file and userdata_file.endswith(".ps1"): - command_prefix = "powershell -ExecutionPolicy Unrestricted -File " - else: - command_prefix = "" - else: - publisher = "Microsoft.Azure.Extensions" - virtual_machine_extension_type = "CustomScript" - type_handler_version = "2.0" - command_prefix = "" - - settings = {} - if userdata: - settings["commandToExecute"] = userdata - elif userdata_file.startswith("http"): - settings["fileUris"] = [userdata_file] - settings["commandToExecute"] = ( - command_prefix - + "./" - + userdata_file[userdata_file.rfind("/") + 1 :] - ) - - custom_extension = { - "resource_group": vm_["resource_group"], - "virtual_machine_name": vm_["name"], - "extension_name": vm_["name"] + "_custom_userdata_script", - "location": vm_["location"], - "publisher": publisher, - "virtual_machine_extension_type": virtual_machine_extension_type, - "type_handler_version": type_handler_version, - "auto_upgrade_minor_version": True, - "settings": settings, - "protected_settings": None, - } - except Exception as exc: # pylint: disable=broad-except - log.exception("Failed to encode userdata: %s", exc) - - params = VirtualMachine( - location=vm_["location"], - plan=None, - hardware_profile=HardwareProfile( - vm_size=getattr(VirtualMachineSizeTypes, vm_["size"].lower(), kwargs), - ), - storage_profile=StorageProfile( - os_disk=os_disk, - data_disks=data_disks, - image_reference=img_ref, - ), - os_profile=OSProfile( - admin_username=vm_username, computer_name=vm_["name"], **os_kwargs - ), - network_profile=NetworkProfile( - network_interfaces=[NetworkInterfaceReference(id=vm_["iface_id"])], - ), - availability_set=availability_set, - ) - - __utils__["cloud.fire_event"]( - "event", - "requesting instance", - "salt/cloud/{}/requesting".format(vm_["name"]), - args=__utils__["cloud.filter_event"]( - "requesting", vm_, ["name", "profile", "provider", "driver"] - ), - sock_dir=__opts__["sock_dir"], - transport=__opts__["transport"], - ) - - try: - vm_create = compconn.virtual_machines.create_or_update( - resource_group_name=vm_["resource_group"], - vm_name=vm_["name"], - parameters=params, - ) - vm_create.wait() - vm_result = vm_create.result() - vm_result = vm_result.as_dict() - if custom_extension: - create_or_update_vmextension(kwargs=custom_extension) - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("compute", exc.message) - vm_result = {} - - return vm_result - - -@_deprecation_message -def create(vm_): - """ - Create a single VM from a data dict. - """ - try: - if ( - vm_["profile"] - and config.is_profile_configured( - __opts__, - _get_active_provider_name() or "azurearm", - vm_["profile"], - vm_=vm_, - ) - is False - ): - return False - except AttributeError: - pass - - if vm_.get("bootstrap_interface") is None: - vm_["bootstrap_interface"] = "public" - - __utils__["cloud.fire_event"]( - "event", - "starting create", - "salt/cloud/{}/creating".format(vm_["name"]), - args=__utils__["cloud.filter_event"]( - "creating", vm_, ["name", "profile", "provider", "driver"] - ), - sock_dir=__opts__["sock_dir"], - transport=__opts__["transport"], - ) - __utils__["cloud.cachedir_index_add"]( - vm_["name"], vm_["profile"], "azurearm", vm_["driver"] - ) - if not vm_.get("location"): - vm_["location"] = get_location(kwargs=vm_) - - log.info("Creating Cloud VM %s in %s", vm_["name"], vm_["location"]) - - vm_request = request_instance(vm_=vm_) - - if not vm_request or "error" in vm_request: - err_message = "Error creating VM {}! ({})".format(vm_["name"], str(vm_request)) - log.error(err_message) - raise SaltCloudSystemExit(err_message) - - def _query_node_data(name, bootstrap_interface): - """ - Query node data. - """ - data = show_instance(name, call="action") - if not data: - return False - ip_address = None - if bootstrap_interface == "public": - ip_address = data["public_ips"][0] - if bootstrap_interface == "private": - ip_address = data["private_ips"][0] - if ip_address is None: - return False - return ip_address - - try: - data = salt.utils.cloud.wait_for_ip( - _query_node_data, - update_args=( - vm_["name"], - vm_["bootstrap_interface"], - ), - timeout=config.get_cloud_config_value( - "wait_for_ip_timeout", vm_, __opts__, default=10 * 60 - ), - interval=config.get_cloud_config_value( - "wait_for_ip_interval", vm_, __opts__, default=10 - ), - interval_multiplier=config.get_cloud_config_value( - "wait_for_ip_interval_multiplier", vm_, __opts__, default=1 - ), - ) - except ( - SaltCloudExecutionTimeout, - SaltCloudExecutionFailure, - SaltCloudSystemExit, - ) as exc: - try: - log.warning(exc) - finally: - raise SaltCloudSystemExit(str(exc)) - - vm_["ssh_host"] = data - if not vm_.get("ssh_username"): - vm_["ssh_username"] = config.get_cloud_config_value( - "ssh_username", vm_, __opts__ - ) - vm_["password"] = config.get_cloud_config_value("ssh_password", vm_, __opts__) - ret = __utils__["cloud.bootstrap"](vm_, __opts__) - - data = show_instance(vm_["name"], call="action") - log.info("Created Cloud VM '%s'", vm_["name"]) - log.debug("'%s' VM creation details:\n%s", vm_["name"], pprint.pformat(data)) - - ret.update(data) - - __utils__["cloud.fire_event"]( - "event", - "created instance", - "salt/cloud/{}/created".format(vm_["name"]), - args=__utils__["cloud.filter_event"]( - "created", vm_, ["name", "profile", "provider", "driver"] - ), - sock_dir=__opts__["sock_dir"], - transport=__opts__["transport"], - ) - - return ret - - -@_deprecation_message -def destroy(name, call=None, kwargs=None): # pylint: disable=unused-argument - """ - Destroy a VM. - - CLI Examples: - - .. code-block:: bash - - salt-cloud -d myminion - salt-cloud -a destroy myminion service_name=myservice - """ - if kwargs is None: - kwargs = {} - - if call == "function": - raise SaltCloudSystemExit( - "The destroy action must be called with -d, --destroy, -a or --action." - ) - - compconn = get_conn(client_type="compute") - - node_data = show_instance(name, call="action") - if node_data["storage_profile"]["os_disk"].get("managed_disk"): - vhd = node_data["storage_profile"]["os_disk"]["managed_disk"]["id"] - else: - vhd = node_data["storage_profile"]["os_disk"]["vhd"]["uri"] - - ret = {name: {}} - log.debug("Deleting VM") - result = compconn.virtual_machines.delete(node_data["resource_group"], name) - result.wait() - - if __opts__.get("update_cachedir", False) is True: - __utils__["cloud.delete_minion_cachedir"]( - name, _get_active_provider_name().split(":")[0], __opts__ - ) - - cleanup_disks = config.get_cloud_config_value( - "cleanup_disks", - get_configured_provider(), - __opts__, - search_global=False, - default=False, - ) - - if cleanup_disks: - cleanup_vhds = kwargs.get( - "delete_vhd", - config.get_cloud_config_value( - "cleanup_vhds", - get_configured_provider(), - __opts__, - search_global=False, - default=False, - ), - ) - - if cleanup_vhds: - log.debug("Deleting vhd") - - comps = vhd.split("/") - container = comps[-2] - blob = comps[-1] - - ret[name]["delete_disk"] = { - "delete_disks": cleanup_disks, - "delete_vhd": cleanup_vhds, - "container": container, - "blob": blob, - } - - if vhd.startswith("http"): - ret[name]["data"] = delete_blob( - kwargs={"container": container, "blob": blob}, call="function" - ) - else: - ret[name]["data"] = delete_managed_disk( - kwargs={ - "resource_group": node_data["resource_group"], - "container": container, - "blob": blob, - }, - call="function", - ) - - cleanup_data_disks = kwargs.get( - "delete_data_disks", - config.get_cloud_config_value( - "cleanup_data_disks", - get_configured_provider(), - __opts__, - search_global=False, - default=False, - ), - ) - - if cleanup_data_disks: - log.debug("Deleting data_disks") - ret[name]["data_disks"] = {} - - for disk in node_data["storage_profile"]["data_disks"]: - datavhd = disk.get("managed_disk", {}).get("id") or disk.get( - "vhd", {} - ).get("uri") - comps = datavhd.split("/") - container = comps[-2] - blob = comps[-1] - - ret[name]["data_disks"][disk["name"]] = { - "delete_disks": cleanup_disks, - "delete_vhd": cleanup_vhds, - "container": container, - "blob": blob, - } - - if datavhd.startswith("http"): - ret[name]["data"] = delete_blob( - kwargs={"container": container, "blob": blob}, call="function" - ) - else: - ret[name]["data"] = delete_managed_disk( - kwargs={ - "resource_group": node_data["resource_group"], - "container": container, - "blob": blob, - }, - call="function", - ) - - cleanup_interfaces = config.get_cloud_config_value( - "cleanup_interfaces", - get_configured_provider(), - __opts__, - search_global=False, - default=False, - ) - - if cleanup_interfaces: - ret[name]["cleanup_network"] = { - "cleanup_interfaces": cleanup_interfaces, - "resource_group": node_data["resource_group"], - "data": [], - } - - ifaces = node_data["network_profile"]["network_interfaces"] - for iface in ifaces: - resource_group = iface["id"].split("/")[4] - ret[name]["cleanup_network"]["data"].append( - delete_interface( - kwargs={ - "resource_group": resource_group, - "iface_name": iface["name"], - }, - call="function", - ) - ) - - return ret - - -@_deprecation_message -def list_storage_accounts(call=None): - """ - List storage accounts within the subscription. - """ - if call == "action": - raise SaltCloudSystemExit( - "The list_storage_accounts function must be called with -f or --function" - ) - - storconn = get_conn(client_type="storage") - - ret = {} - try: - accounts_query = storconn.storage_accounts.list() - accounts = salt.utils.azurearm.paged_object_to_list(accounts_query) - for account in accounts: - ret[account["name"]] = account - except CloudError as exc: - salt.utils.azurearm.log_cloud_error("storage", exc.message) - ret = {"Error": exc.message} - - return ret - - -def _get_cloud_environment(): - """ - Get the cloud environment object. - """ - cloud_environment = config.get_cloud_config_value( - "cloud_environment", get_configured_provider(), __opts__, search_global=False - ) - try: - cloud_env_module = importlib.import_module("msrestazure.azure_cloud") - cloud_env = getattr(cloud_env_module, cloud_environment or "AZURE_PUBLIC_CLOUD") - except (AttributeError, ImportError): - raise SaltCloudSystemExit( - "The azure {} cloud environment is not available.".format(cloud_environment) - ) - - return cloud_env - - -def _get_block_blob_service(kwargs=None): - """ - Get the block blob storage service. - """ - resource_group = kwargs.get("resource_group") or config.get_cloud_config_value( - "resource_group", get_configured_provider(), __opts__, search_global=False - ) - sas_token = kwargs.get("sas_token") or config.get_cloud_config_value( - "sas_token", get_configured_provider(), __opts__, search_global=False - ) - storage_account = kwargs.get("storage_account") or config.get_cloud_config_value( - "storage_account", get_configured_provider(), __opts__, search_global=False - ) - storage_key = kwargs.get("storage_key") or config.get_cloud_config_value( - "storage_key", get_configured_provider(), __opts__, search_global=False - ) - - if not resource_group: - raise SaltCloudSystemExit("A resource group must be specified") - - if not storage_account: - raise SaltCloudSystemExit("A storage account must be specified") - - if not storage_key: - storconn = get_conn(client_type="storage") - storage_keys = storconn.storage_accounts.list_keys( - resource_group, storage_account - ) - storage_keys = {v.key_name: v.value for v in storage_keys.keys} - storage_key = next(iter(storage_keys.values())) - - cloud_env = _get_cloud_environment() - - endpoint_suffix = cloud_env.suffixes.storage_endpoint - - return BlockBlobService( - storage_account, - storage_key, - sas_token=sas_token, - endpoint_suffix=endpoint_suffix, - ) - - -@_deprecation_message -def list_blobs(call=None, kwargs=None): # pylint: disable=unused-argument - """ - List blobs. - """ - if kwargs is None: - kwargs = {} - - if "container" not in kwargs: - raise SaltCloudSystemExit("A container must be specified") - - storageservice = _get_block_blob_service(kwargs) - - ret = {} - try: - for blob in storageservice.list_blobs(kwargs["container"]).items: - ret[blob.name] = { - "blob_type": blob.properties.blob_type, - "last_modified": blob.properties.last_modified.isoformat(), - "server_encrypted": blob.properties.server_encrypted, - } - except Exception as exc: # pylint: disable=broad-except - log.warning(str(exc)) - - return ret - - -@_deprecation_message -def delete_blob(call=None, kwargs=None): # pylint: disable=unused-argument - """ - Delete a blob from a container. - """ - if kwargs is None: - kwargs = {} - - if "container" not in kwargs: - raise SaltCloudSystemExit("A container must be specified") - - if "blob" not in kwargs: - raise SaltCloudSystemExit("A blob must be specified") - - storageservice = _get_block_blob_service(kwargs) - - storageservice.delete_blob(kwargs["container"], kwargs["blob"]) - return True - - -@_deprecation_message -def delete_managed_disk(call=None, kwargs=None): # pylint: disable=unused-argument - """ - Delete a managed disk from a resource group. - """ - - compconn = get_conn(client_type="compute") - - try: - compconn.disks.delete(kwargs["resource_group"], kwargs["blob"]) - except Exception as exc: # pylint: disable=broad-except - log.error( - "Error deleting managed disk %s - %s", - kwargs.get("blob"), - str(exc), - ) - return False - - return True - - -@_deprecation_message -def list_virtual_networks(call=None, kwargs=None): - """ - List virtual networks. - """ - if kwargs is None: - kwargs = {} - - if call == "action": - raise SaltCloudSystemExit( - "The avail_sizes function must be called with -f or --function" - ) - - netconn = get_conn(client_type="network") - resource_groups = list_resource_groups() - - ret = {} - for group in resource_groups: - try: - networks = netconn.virtual_networks.list(resource_group_name=group) - except CloudError: - networks = {} - for network_obj in networks: - network = network_obj.as_dict() - ret[network["name"]] = network - ret[network["name"]]["subnets"] = list_subnets( - kwargs={"resource_group": group, "network": network["name"]} - ) - - return ret - - -@_deprecation_message -def list_subnets(call=None, kwargs=None): - """ - List subnets in a virtual network. - """ - if kwargs is None: - kwargs = {} - - if call == "action": - raise SaltCloudSystemExit( - "The avail_sizes function must be called with -f or --function" - ) - - netconn = get_conn(client_type="network") - - resource_group = kwargs.get("resource_group") or config.get_cloud_config_value( - "resource_group", get_configured_provider(), __opts__, search_global=False - ) - - if not resource_group and "group" in kwargs and "resource_group" not in kwargs: - resource_group = kwargs["group"] - - if not resource_group: - raise SaltCloudSystemExit("A resource group must be specified") - - if kwargs.get("network") is None: - kwargs["network"] = config.get_cloud_config_value( - "network", get_configured_provider(), __opts__, search_global=False - ) - - if "network" not in kwargs or kwargs["network"] is None: - raise SaltCloudSystemExit('A "network" must be specified') - - ret = {} - subnets = netconn.subnets.list(resource_group, kwargs["network"]) - for subnet in subnets: - ret[subnet.name] = subnet.as_dict() - ret[subnet.name]["ip_configurations"] = {} - for ip_ in subnet.ip_configurations: - comps = ip_.id.split("/") - name = comps[-1] - ret[subnet.name]["ip_configurations"][name] = ip_.as_dict() - ret[subnet.name]["ip_configurations"][name]["subnet"] = subnet.name - ret[subnet.name]["resource_group"] = resource_group - return ret - - -@_deprecation_message -def create_or_update_vmextension( - call=None, kwargs=None -): # pylint: disable=unused-argument - """ - .. versionadded:: 2019.2.0 - - Create or update a VM extension object "inside" of a VM object. - - required kwargs: - .. code-block:: yaml - - extension_name: myvmextension - virtual_machine_name: myvm - settings: {"commandToExecute": "hostname"} - - optional kwargs: - .. code-block:: yaml - - resource_group: < inferred from cloud configs > - location: < inferred from cloud configs > - publisher: < default: Microsoft.Azure.Extensions > - virtual_machine_extension_type: < default: CustomScript > - type_handler_version: < default: 2.0 > - auto_upgrade_minor_version: < default: True > - protected_settings: < default: None > - """ - if kwargs is None: - kwargs = {} - - if "extension_name" not in kwargs: - raise SaltCloudSystemExit("An extension name must be specified") - - if "virtual_machine_name" not in kwargs: - raise SaltCloudSystemExit("A virtual machine name must be specified") - - compconn = get_conn(client_type="compute") - - # pylint: disable=invalid-name - VirtualMachineExtension = getattr(compute_models, "VirtualMachineExtension") - - resource_group = kwargs.get("resource_group") or config.get_cloud_config_value( - "resource_group", get_configured_provider(), __opts__, search_global=False - ) - - if not resource_group: - raise SaltCloudSystemExit("A resource group must be specified") - - location = kwargs.get("location") or get_location() - - if not location: - raise SaltCloudSystemExit("A location must be specified") - - publisher = kwargs.get("publisher", "Microsoft.Azure.Extensions") - virtual_machine_extension_type = kwargs.get( - "virtual_machine_extension_type", "CustomScript" - ) - type_handler_version = kwargs.get("type_handler_version", "2.0") - auto_upgrade_minor_version = kwargs.get("auto_upgrade_minor_version", True) - settings = kwargs.get("settings", {}) - protected_settings = kwargs.get("protected_settings") - - if not isinstance(settings, dict): - raise SaltCloudSystemExit("VM extension settings are not valid") - elif "commandToExecute" not in settings and "script" not in settings: - raise SaltCloudSystemExit( - "VM extension settings are not valid. Either commandToExecute or script" - " must be specified." - ) - - log.info("Creating VM extension %s", kwargs["extension_name"]) - - ret = {} - try: - params = VirtualMachineExtension( - location=location, - publisher=publisher, - virtual_machine_extension_type=virtual_machine_extension_type, - type_handler_version=type_handler_version, - auto_upgrade_minor_version=auto_upgrade_minor_version, - settings=settings, - protected_settings=protected_settings, - ) - poller = compconn.virtual_machine_extensions.create_or_update( - resource_group, - kwargs["virtual_machine_name"], - kwargs["extension_name"], - params, - ) - ret = poller.result() - ret = ret.as_dict() - - except CloudError as exc: - salt.utils.azurearm.log_cloud_error( - "compute", - "Error attempting to create the VM extension: {}".format(exc.message), - ) - ret = {"error": exc.message} - - return ret - - -@_deprecation_message -def stop(name, call=None): - """ - .. versionadded:: 2019.2.0 - - Stop (deallocate) a VM - - CLI Examples: - - .. code-block:: bash - - salt-cloud -a stop myminion - """ - if call == "function": - raise SaltCloudSystemExit("The stop action must be called with -a or --action.") - - compconn = get_conn(client_type="compute") - - resource_group = config.get_cloud_config_value( - "resource_group", get_configured_provider(), __opts__, search_global=False - ) - - ret = {} - if not resource_group: - groups = list_resource_groups() - for group in groups: - try: - instance = compconn.virtual_machines.deallocate( - vm_name=name, resource_group_name=group - ) - instance.wait() - vm_result = instance.result() - ret = vm_result.as_dict() - break - except CloudError as exc: - if "was not found" in exc.message: - continue - else: - ret = {"error": exc.message} - if not ret: - salt.utils.azurearm.log_cloud_error( - "compute", "Unable to find virtual machine with name: {}".format(name) - ) - ret = {"error": "Unable to find virtual machine with name: {}".format(name)} - else: - try: - instance = compconn.virtual_machines.deallocate( - vm_name=name, resource_group_name=resource_group - ) - instance.wait() - vm_result = instance.result() - ret = vm_result.as_dict() - except CloudError as exc: - salt.utils.azurearm.log_cloud_error( - "compute", "Error attempting to stop {}: {}".format(name, exc.message) - ) - ret = {"error": exc.message} - - return ret - - -@_deprecation_message -def start(name, call=None): - """ - .. versionadded:: 2019.2.0 - - Start a VM - - CLI Examples: - - .. code-block:: bash - - salt-cloud -a start myminion - """ - if call == "function": - raise SaltCloudSystemExit( - "The start action must be called with -a or --action." - ) - - compconn = get_conn(client_type="compute") - - resource_group = config.get_cloud_config_value( - "resource_group", get_configured_provider(), __opts__, search_global=False - ) - - ret = {} - if not resource_group: - groups = list_resource_groups() - for group in groups: - try: - instance = compconn.virtual_machines.start( - vm_name=name, resource_group_name=group - ) - instance.wait() - vm_result = instance.result() - ret = vm_result.as_dict() - break - except CloudError as exc: - if "was not found" in exc.message: - continue - else: - ret = {"error": exc.message} - if not ret: - salt.utils.azurearm.log_cloud_error( - "compute", "Unable to find virtual machine with name: {}".format(name) - ) - ret = {"error": "Unable to find virtual machine with name: {}".format(name)} - else: - try: - instance = compconn.virtual_machines.start( - vm_name=name, resource_group_name=resource_group - ) - instance.wait() - vm_result = instance.result() - ret = vm_result.as_dict() - except CloudError as exc: - salt.utils.azurearm.log_cloud_error( - "compute", - "Error attempting to start {}: {}".format(name, exc.message), - ) - ret = {"error": exc.message} - - return ret diff --git a/salt/cloud/clouds/msazure.py b/salt/cloud/clouds/msazure.py deleted file mode 100644 index 8d5b74e701c..00000000000 --- a/salt/cloud/clouds/msazure.py +++ /dev/null @@ -1,3665 +0,0 @@ -""" -Azure Cloud Module -================== - -The Azure cloud module is used to control access to Microsoft Azure - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 due to - the deprecation of the "Classic" API for Azure. Please migrate to - `Azure Resource Manager by March 1, 2023 - `_ - -:depends: - * `Microsoft Azure SDK for Python `_ >= 1.0.2 - * python-requests, for Python < 2.7.9 -:configuration: - Required provider parameters: - - * ``apikey`` - * ``certificate_path`` - * ``subscription_id`` - * ``backend`` - - A Management Certificate (.pem and .crt files) must be created and the .pem - file placed on the same machine that salt-cloud is run from. Information on - creating the pem file to use, and uploading the associated cer file can be - found at: - - http://www.windowsazure.com/en-us/develop/python/how-to-guides/service-management/ - - For users with Python < 2.7.9, ``backend`` must currently be set to ``requests``. - -Example ``/etc/salt/cloud.providers`` or -``/etc/salt/cloud.providers.d/azure.conf`` configuration: - -.. code-block:: yaml - - my-azure-config: - driver: azure - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - certificate_path: /etc/salt/azure.pem - management_host: management.core.windows.net -""" -# pylint: disable=function-redefined - -import copy -import logging -import pprint -import time -from functools import wraps - -import salt.config as config -import salt.utils.args -import salt.utils.cloud -import salt.utils.stringutils -import salt.utils.versions -import salt.utils.yaml -from salt.exceptions import SaltCloudSystemExit - -HAS_LIBS = False -try: - import azure - import azure.servicemanagement - import azure.storage - from azure.common import ( - AzureConflictHttpError, - AzureException, - AzureMissingResourceHttpError, - ) - - import salt.utils.msazure - from salt.utils.msazure import object_to_dict - - HAS_LIBS = True -except ImportError: - pass - -__virtualname__ = "azure" - - -# Get logging started -log = logging.getLogger(__name__) - - -# Only load in this module if the AZURE configurations are in place -def __virtual__(): - """ - Check for Azure configurations. - """ - if get_configured_provider() is False: - return False - - if get_dependencies() is False: - return False - - return __virtualname__ - - -def _get_active_provider_name(): - try: - return __active_provider_name__.value() - except AttributeError: - return __active_provider_name__ - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about msazure deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "This cloud provider will be removed from Salt in version 3007 due to " - "the deprecation of the 'Classic' API for Azure. Please migrate to " - "Azure Resource Manager by March 1, 2023 " - "(https://docs.microsoft.com/en-us/azure/virtual-machines/classic-vm-deprecation)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -def get_configured_provider(): - """ - Return the first configured instance. - """ - return config.is_provider_configured( - __opts__, - _get_active_provider_name() or __virtualname__, - ("subscription_id", "certificate_path"), - ) - - -@_deprecation_message -def get_dependencies(): - """ - Warn if dependencies aren't met. - """ - return config.check_driver_dependencies(__virtualname__, {"azure": HAS_LIBS}) - - -@_deprecation_message -def get_conn(): - """ - Return a conn object for the passed VM data - """ - certificate_path = config.get_cloud_config_value( - "certificate_path", get_configured_provider(), __opts__, search_global=False - ) - subscription_id = salt.utils.stringutils.to_str( - config.get_cloud_config_value( - "subscription_id", get_configured_provider(), __opts__, search_global=False - ) - ) - management_host = config.get_cloud_config_value( - "management_host", - get_configured_provider(), - __opts__, - search_global=False, - default="management.core.windows.net", - ) - return azure.servicemanagement.ServiceManagementService( - subscription_id, certificate_path, management_host - ) - - -@_deprecation_message -def script(vm_): - """ - Return the script deployment object - """ - return salt.utils.cloud.os_script( - config.get_cloud_config_value("script", vm_, __opts__), - vm_, - __opts__, - salt.utils.cloud.salt_config_to_yaml( - salt.utils.cloud.minion_config(__opts__, vm_) - ), - ) - - -@_deprecation_message -def avail_locations(conn=None, call=None): - """ - List available locations for Azure - """ - if call == "action": - raise SaltCloudSystemExit( - "The avail_locations function must be called with " - "-f or --function, or with the --list-locations option" - ) - - if not conn: - conn = get_conn() - - ret = {} - locations = conn.list_locations() - for location in locations: - ret[location.name] = { - "name": location.name, - "display_name": location.display_name, - "available_services": location.available_services, - } - return ret - - -@_deprecation_message -def avail_images(conn=None, call=None): - """ - List available images for Azure - """ - if call == "action": - raise SaltCloudSystemExit( - "The avail_images function must be called with " - "-f or --function, or with the --list-images option" - ) - - if not conn: - conn = get_conn() - - ret = {} - for item in conn.list_os_images(): - ret[item.name] = object_to_dict(item) - for item in conn.list_vm_images(): - ret[item.name] = object_to_dict(item) - return ret - - -@_deprecation_message -def avail_sizes(call=None): - """ - Return a list of sizes from Azure - """ - if call == "action": - raise SaltCloudSystemExit( - "The avail_sizes function must be called with " - "-f or --function, or with the --list-sizes option" - ) - - conn = get_conn() - data = conn.list_role_sizes() - ret = {} - for item in data.role_sizes: - ret[item.name] = object_to_dict(item) - return ret - - -@_deprecation_message -def list_nodes(conn=None, call=None): - """ - List VMs on this Azure account - """ - if call == "action": - raise SaltCloudSystemExit( - "The list_nodes function must be called with -f or --function." - ) - - ret = {} - nodes = list_nodes_full(conn, call) - for node in nodes: - ret[node] = {"name": node} - for prop in ("id", "image", "size", "state", "private_ips", "public_ips"): - ret[node][prop] = nodes[node].get(prop) - return ret - - -@_deprecation_message -def list_nodes_full(conn=None, call=None): - """ - List VMs on this Azure account, with full information - """ - if call == "action": - raise SaltCloudSystemExit( - "The list_nodes_full function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - ret = {} - services = list_hosted_services(conn=conn, call=call) - for service in services: - for deployment in services[service]["deployments"]: - deploy_dict = services[service]["deployments"][deployment] - deploy_dict_no_role_info = copy.deepcopy(deploy_dict) - del deploy_dict_no_role_info["role_list"] - del deploy_dict_no_role_info["role_instance_list"] - roles = deploy_dict["role_list"] - for role in roles: - role_instances = deploy_dict["role_instance_list"] - ret[role] = roles[role] - ret[role].update(role_instances[role]) - ret[role]["id"] = role - ret[role]["hosted_service"] = service - if role_instances[role]["power_state"] == "Started": - ret[role]["state"] = "running" - elif role_instances[role]["power_state"] == "Stopped": - ret[role]["state"] = "stopped" - else: - ret[role]["state"] = "pending" - ret[role]["private_ips"] = [] - ret[role]["public_ips"] = [] - ret[role]["deployment"] = deploy_dict_no_role_info - ret[role]["url"] = deploy_dict["url"] - ip_address = role_instances[role]["ip_address"] - if ip_address: - if salt.utils.cloud.is_public_ip(ip_address): - ret[role]["public_ips"].append(ip_address) - else: - ret[role]["private_ips"].append(ip_address) - ret[role]["size"] = role_instances[role]["instance_size"] - ret[role]["image"] = roles[role]["role_info"]["os_virtual_hard_disk"][ - "source_image_name" - ] - return ret - - -@_deprecation_message -def list_hosted_services(conn=None, call=None): - """ - List VMs on this Azure account, with full information - """ - if call == "action": - raise SaltCloudSystemExit( - "The list_hosted_services function must be called with -f or --function" - ) - - if not conn: - conn = get_conn() - - ret = {} - services = conn.list_hosted_services() - for service in services: - props = service.hosted_service_properties - ret[service.service_name] = { - "name": service.service_name, - "url": service.url, - "affinity_group": props.affinity_group, - "date_created": props.date_created, - "date_last_modified": props.date_last_modified, - "description": props.description, - "extended_properties": props.extended_properties, - "label": props.label, - "location": props.location, - "status": props.status, - "deployments": {}, - } - deployments = conn.get_hosted_service_properties( - service_name=service.service_name, embed_detail=True - ) - for deployment in deployments.deployments: - ret[service.service_name]["deployments"][deployment.name] = { - "configuration": deployment.configuration, - "created_time": deployment.created_time, - "deployment_slot": deployment.deployment_slot, - "extended_properties": deployment.extended_properties, - "input_endpoint_list": deployment.input_endpoint_list, - "label": deployment.label, - "last_modified_time": deployment.last_modified_time, - "locked": deployment.locked, - "name": deployment.name, - "persistent_vm_downtime_info": deployment.persistent_vm_downtime_info, - "private_id": deployment.private_id, - "role_instance_list": {}, - "role_list": {}, - "rollback_allowed": deployment.rollback_allowed, - "sdk_version": deployment.sdk_version, - "status": deployment.status, - "upgrade_domain_count": deployment.upgrade_domain_count, - "upgrade_status": deployment.upgrade_status, - "url": deployment.url, - } - for role_instance in deployment.role_instance_list: - ret[service.service_name]["deployments"][deployment.name][ - "role_instance_list" - ][role_instance.role_name] = { - "fqdn": role_instance.fqdn, - "instance_error_code": role_instance.instance_error_code, - "instance_fault_domain": role_instance.instance_fault_domain, - "instance_name": role_instance.instance_name, - "instance_size": role_instance.instance_size, - "instance_state_details": role_instance.instance_state_details, - "instance_status": role_instance.instance_status, - "instance_upgrade_domain": role_instance.instance_upgrade_domain, - "ip_address": role_instance.ip_address, - "power_state": role_instance.power_state, - "role_name": role_instance.role_name, - } - for role in deployment.role_list: - ret[service.service_name]["deployments"][deployment.name]["role_list"][ - role.role_name - ] = { - "role_name": role.role_name, - "os_version": role.os_version, - } - role_info = conn.get_role( - service_name=service.service_name, - deployment_name=deployment.name, - role_name=role.role_name, - ) - ret[service.service_name]["deployments"][deployment.name]["role_list"][ - role.role_name - ]["role_info"] = { - "availability_set_name": role_info.availability_set_name, - "configuration_sets": role_info.configuration_sets, - "data_virtual_hard_disks": role_info.data_virtual_hard_disks, - "os_version": role_info.os_version, - "role_name": role_info.role_name, - "role_size": role_info.role_size, - "role_type": role_info.role_type, - } - ret[service.service_name]["deployments"][deployment.name]["role_list"][ - role.role_name - ]["role_info"]["os_virtual_hard_disk"] = { - "disk_label": role_info.os_virtual_hard_disk.disk_label, - "disk_name": role_info.os_virtual_hard_disk.disk_name, - "host_caching": role_info.os_virtual_hard_disk.host_caching, - "media_link": role_info.os_virtual_hard_disk.media_link, - "os": role_info.os_virtual_hard_disk.os, - "source_image_name": role_info.os_virtual_hard_disk.source_image_name, - } - return ret - - -@_deprecation_message -def list_nodes_select(conn=None, call=None): - """ - Return a list of the VMs that are on the provider, with select fields - """ - if not conn: - conn = get_conn() - - return salt.utils.cloud.list_nodes_select( - list_nodes_full(conn, "function"), - __opts__["query.selection"], - call, - ) - - -@_deprecation_message -def show_instance(name, call=None): - """ - Show the details from the provider concerning an instance - """ - if call != "action": - raise SaltCloudSystemExit( - "The show_instance action must be called with -a or --action." - ) - - nodes = list_nodes_full() - # Find under which cloud service the name is listed, if any - if name not in nodes: - return {} - if "name" not in nodes[name]: - nodes[name]["name"] = nodes[name]["id"] - try: - __utils__["cloud.cache_node"]( - nodes[name], _get_active_provider_name(), __opts__ - ) - except TypeError: - log.warning( - "Unable to show cache node data; this may be because the node has been" - " deleted" - ) - return nodes[name] - - -@_deprecation_message -def create(vm_): - """ - Create a single VM from a data dict - """ - try: - # Check for required profile parameters before sending any API calls. - if ( - vm_["profile"] - and config.is_profile_configured( - __opts__, - _get_active_provider_name() or "azure", - vm_["profile"], - vm_=vm_, - ) - is False - ): - return False - except AttributeError: - pass - - __utils__["cloud.fire_event"]( - "event", - "starting create", - "salt/cloud/{}/creating".format(vm_["name"]), - args=__utils__["cloud.filter_event"]( - "creating", vm_, ["name", "profile", "provider", "driver"] - ), - sock_dir=__opts__["sock_dir"], - transport=__opts__["transport"], - ) - - log.info("Creating Cloud VM %s", vm_["name"]) - conn = get_conn() - - label = vm_.get("label", vm_["name"]) - service_name = vm_.get("service_name", vm_["name"]) - service_kwargs = { - "service_name": service_name, - "label": label, - "description": vm_.get("desc", vm_["name"]), - } - - loc_error = False - if "location" in vm_: - if "affinity_group" in vm_: - loc_error = True - else: - service_kwargs["location"] = vm_["location"] - elif "affinity_group" in vm_: - service_kwargs["affinity_group"] = vm_["affinity_group"] - else: - loc_error = True - - if loc_error: - raise SaltCloudSystemExit( - "Either a location or affinity group must be specified, but not both" - ) - - ssh_port = config.get_cloud_config_value( - "port", vm_, __opts__, default=22, search_global=True - ) - - ssh_endpoint = azure.servicemanagement.ConfigurationSetInputEndpoint( - name="SSH", - protocol="TCP", - port=ssh_port, - local_port=22, - ) - - network_config = azure.servicemanagement.ConfigurationSet() - network_config.input_endpoints.input_endpoints.append(ssh_endpoint) - network_config.configuration_set_type = "NetworkConfiguration" - - if "win_username" in vm_: - system_config = azure.servicemanagement.WindowsConfigurationSet( - computer_name=vm_["name"], - admin_username=vm_["win_username"], - admin_password=vm_["win_password"], - ) - - smb_port = "445" - if "smb_port" in vm_: - smb_port = vm_["smb_port"] - - smb_endpoint = azure.servicemanagement.ConfigurationSetInputEndpoint( - name="SMB", - protocol="TCP", - port=smb_port, - local_port=smb_port, - ) - - network_config.input_endpoints.input_endpoints.append(smb_endpoint) - - # Domain and WinRM configuration not yet supported by Salt Cloud - system_config.domain_join = None - system_config.win_rm = None - - else: - system_config = azure.servicemanagement.LinuxConfigurationSet( - host_name=vm_["name"], - user_name=vm_["ssh_username"], - user_password=vm_["ssh_password"], - disable_ssh_password_authentication=False, - ) - - # TODO: Might need to create a storage account - media_link = vm_["media_link"] - # TODO: Probably better to use more than just the name in the media_link - media_link += "/{}.vhd".format(vm_["name"]) - os_hd = azure.servicemanagement.OSVirtualHardDisk(vm_["image"], media_link) - - vm_kwargs = { - "service_name": service_name, - "deployment_name": service_name, - "deployment_slot": vm_["slot"], - "label": label, - "role_name": vm_["name"], - "system_config": system_config, - "os_virtual_hard_disk": os_hd, - "role_size": vm_["size"], - "network_config": network_config, - } - - if "virtual_network_name" in vm_: - vm_kwargs["virtual_network_name"] = vm_["virtual_network_name"] - if "subnet_name" in vm_: - network_config.subnet_names.append(vm_["subnet_name"]) - - log.debug("vm_kwargs: %s", vm_kwargs) - - event_kwargs = { - "service_kwargs": service_kwargs.copy(), - "vm_kwargs": vm_kwargs.copy(), - } - del event_kwargs["vm_kwargs"]["system_config"] - del event_kwargs["vm_kwargs"]["os_virtual_hard_disk"] - del event_kwargs["vm_kwargs"]["network_config"] - __utils__["cloud.fire_event"]( - "event", - "requesting instance", - "salt/cloud/{}/requesting".format(vm_["name"]), - args=__utils__["cloud.filter_event"]( - "requesting", event_kwargs, list(event_kwargs) - ), - sock_dir=__opts__["sock_dir"], - transport=__opts__["transport"], - ) - log.debug("vm_kwargs: %s", vm_kwargs) - - # Azure lets you open winrm on a new VM - # Can open up specific ports in Azure; but not on Windows - try: - conn.create_hosted_service(**service_kwargs) - except AzureConflictHttpError: - log.debug("Cloud service already exists") - except Exception as exc: # pylint: disable=broad-except - error = "The hosted service name is invalid." - if error in str(exc): - log.error( - "Error creating %s on Azure.\n\n" - "The hosted service name is invalid. The name can contain " - "only letters, numbers, and hyphens. The name must start with " - "a letter and must end with a letter or a number.", - vm_["name"], - # Show the traceback if the debug logging level is enabled - exc_info_on_loglevel=logging.DEBUG, - ) - else: - log.error( - "Error creating %s on Azure\n\n" - "The following exception was thrown when trying to " - "run the initial deployment: \n%s", - vm_["name"], - exc, - # Show the traceback if the debug logging level is enabled - exc_info_on_loglevel=logging.DEBUG, - ) - return False - try: - result = conn.create_virtual_machine_deployment(**vm_kwargs) - log.debug("Request ID for machine: %s", result.request_id) - _wait_for_async(conn, result.request_id) - except AzureConflictHttpError: - log.debug("Conflict error. The deployment may already exist, trying add_role") - # Deleting two useless keywords - del vm_kwargs["deployment_slot"] - del vm_kwargs["label"] - del vm_kwargs["virtual_network_name"] - result = conn.add_role(**vm_kwargs) # pylint: disable=unexpected-keyword-arg - _wait_for_async(conn, result.request_id) - except Exception as exc: # pylint: disable=broad-except - error = "The hosted service name is invalid." - if error in str(exc): - log.error( - "Error creating %s on Azure.\n\n" - "The VM name is invalid. The name can contain " - "only letters, numbers, and hyphens. The name must start with " - "a letter and must end with a letter or a number.", - vm_["name"], - # Show the traceback if the debug logging level is enabled - exc_info_on_loglevel=logging.DEBUG, - ) - else: - log.error( - "Error creating %s on Azure.\n\n" - "The Virtual Machine could not be created. If you " - "are using an already existing Cloud Service, " - "make sure you set up the `port` variable corresponding " - "to the SSH port exists and that the port number is not " - "already in use.\nThe following exception was thrown when trying to " - "run the initial deployment: \n%s", - vm_["name"], - exc, - # Show the traceback if the debug logging level is enabled - exc_info_on_loglevel=logging.DEBUG, - ) - return False - - def wait_for_hostname(): - """ - Wait for the IP address to become available - """ - try: - conn.get_role(service_name, service_name, vm_["name"]) - data = show_instance(vm_["name"], call="action") - if "url" in data and data["url"] != "": - return data["url"] - except AzureMissingResourceHttpError: - pass - time.sleep(1) - return False - - hostname = salt.utils.cloud.wait_for_fun( - wait_for_hostname, - timeout=config.get_cloud_config_value( - "wait_for_fun_timeout", vm_, __opts__, default=15 * 60 - ), - ) - - if not hostname: - log.error("Failed to get a value for the hostname.") - return False - - vm_["ssh_host"] = hostname.replace("http://", "").replace("/", "") - vm_["password"] = config.get_cloud_config_value("ssh_password", vm_, __opts__) - ret = __utils__["cloud.bootstrap"](vm_, __opts__) - - # Attaching volumes - volumes = config.get_cloud_config_value( - "volumes", vm_, __opts__, search_global=True - ) - if volumes: - __utils__["cloud.fire_event"]( - "event", - "attaching volumes", - "salt/cloud/{}/attaching_volumes".format(vm_["name"]), - args=__utils__["cloud.filter_event"]("attaching_volumes", vm_, ["volumes"]), - sock_dir=__opts__["sock_dir"], - transport=__opts__["transport"], - ) - - log.info("Create and attach volumes to node %s", vm_["name"]) - created = create_attach_volumes( - vm_["name"], - { - "volumes": volumes, - "service_name": service_name, - "deployment_name": vm_["name"], - "media_link": media_link, - "role_name": vm_["name"], - "del_all_vols_on_destroy": vm_.get( - "set_del_all_vols_on_destroy", False - ), - }, - call="action", - ) - ret["Attached Volumes"] = created - - data = show_instance(vm_["name"], call="action") - log.info("Created Cloud VM '%s'", vm_) - log.debug("'%s' VM creation details:\n%s", vm_["name"], pprint.pformat(data)) - - ret.update(data) - - __utils__["cloud.fire_event"]( - "event", - "created instance", - "salt/cloud/{}/created".format(vm_["name"]), - args=__utils__["cloud.filter_event"]( - "created", vm_, ["name", "profile", "provider", "driver"] - ), - sock_dir=__opts__["sock_dir"], - transport=__opts__["transport"], - ) - - return ret - - -@_deprecation_message -def create_attach_volumes(name, kwargs, call=None, wait_to_finish=True): - """ - Create and attach volumes to created node - """ - if call != "action": - raise SaltCloudSystemExit( - "The create_attach_volumes action must be called with -a or --action." - ) - - if kwargs is None: - kwargs = {} - - if isinstance(kwargs["volumes"], str): - volumes = salt.utils.yaml.safe_load(kwargs["volumes"]) - else: - volumes = kwargs["volumes"] - - # From the Azure .NET SDK doc - # - # The Create Data Disk operation adds a data disk to a virtual - # machine. There are three ways to create the data disk using the - # Add Data Disk operation. - # Option 1 - Attach an empty data disk to - # the role by specifying the disk label and location of the disk - # image. Do not include the DiskName and SourceMediaLink elements in - # the request body. Include the MediaLink element and reference a - # blob that is in the same geographical region as the role. You can - # also omit the MediaLink element. In this usage, Azure will create - # the data disk in the storage account configured as default for the - # role. - # Option 2 - Attach an existing data disk that is in the image - # repository. Do not include the DiskName and SourceMediaLink - # elements in the request body. Specify the data disk to use by - # including the DiskName element. Note: If included the in the - # response body, the MediaLink and LogicalDiskSizeInGB elements are - # ignored. - # Option 3 - Specify the location of a blob in your storage - # account that contain a disk image to use. Include the - # SourceMediaLink element. Note: If the MediaLink element - # isincluded, it is ignored. (see - # http://msdn.microsoft.com/en-us/library/windowsazure/jj157199.aspx - # for more information) - # - # Here only option 1 is implemented - conn = get_conn() - ret = [] - for volume in volumes: - if "disk_name" in volume: - log.error("You cannot specify a disk_name. Only new volumes are allowed") - return False - # Use the size keyword to set a size, but you can use the - # azure name too. If neither is set, the disk has size 100GB - volume.setdefault("logical_disk_size_in_gb", volume.get("size", 100)) - volume.setdefault("host_caching", "ReadOnly") - volume.setdefault("lun", 0) - # The media link is vm_name-disk-[0-15].vhd - volume.setdefault( - "media_link", - kwargs["media_link"][:-4] + "-disk-{}.vhd".format(volume["lun"]), - ) - volume.setdefault( - "disk_label", kwargs["role_name"] + "-disk-{}".format(volume["lun"]) - ) - volume_dict = {"volume_name": volume["lun"], "disk_label": volume["disk_label"]} - - # Preparing the volume dict to be passed with ** - kwargs_add_data_disk = [ - "lun", - "host_caching", - "media_link", - "disk_label", - "disk_name", - "logical_disk_size_in_gb", - "source_media_link", - ] - for key in set(volume.keys()) - set(kwargs_add_data_disk): - del volume[key] - - attach = conn.add_data_disk( - kwargs["service_name"], - kwargs["deployment_name"], - kwargs["role_name"], - **volume - ) - log.debug(attach) - - # If attach is None then everything is fine - if attach: - msg = "{} attached to {} (aka {})".format( - volume_dict["volume_name"], - kwargs["role_name"], - name, - ) - log.info(msg) - ret.append(msg) - else: - log.error("Error attaching %s on Azure", volume_dict) - return ret - - -@_deprecation_message -def create_attach_volumes(name, kwargs, call=None, wait_to_finish=True): - """ - Create and attach volumes to created node - """ - if call != "action": - raise SaltCloudSystemExit( - "The create_attach_volumes action must be called with -a or --action." - ) - - if kwargs is None: - kwargs = {} - - if isinstance(kwargs["volumes"], str): - volumes = salt.utils.yaml.safe_load(kwargs["volumes"]) - else: - volumes = kwargs["volumes"] - - # From the Azure .NET SDK doc - # - # The Create Data Disk operation adds a data disk to a virtual - # machine. There are three ways to create the data disk using the - # Add Data Disk operation. - # Option 1 - Attach an empty data disk to - # the role by specifying the disk label and location of the disk - # image. Do not include the DiskName and SourceMediaLink elements in - # the request body. Include the MediaLink element and reference a - # blob that is in the same geographical region as the role. You can - # also omit the MediaLink element. In this usage, Azure will create - # the data disk in the storage account configured as default for the - # role. - # Option 2 - Attach an existing data disk that is in the image - # repository. Do not include the DiskName and SourceMediaLink - # elements in the request body. Specify the data disk to use by - # including the DiskName element. Note: If included the in the - # response body, the MediaLink and LogicalDiskSizeInGB elements are - # ignored. - # Option 3 - Specify the location of a blob in your storage - # account that contain a disk image to use. Include the - # SourceMediaLink element. Note: If the MediaLink element - # isincluded, it is ignored. (see - # http://msdn.microsoft.com/en-us/library/windowsazure/jj157199.aspx - # for more information) - # - # Here only option 1 is implemented - conn = get_conn() - ret = [] - for volume in volumes: - if "disk_name" in volume: - log.error("You cannot specify a disk_name. Only new volumes are allowed") - return False - # Use the size keyword to set a size, but you can use the - # azure name too. If neither is set, the disk has size 100GB - volume.setdefault("logical_disk_size_in_gb", volume.get("size", 100)) - volume.setdefault("host_caching", "ReadOnly") - volume.setdefault("lun", 0) - # The media link is vm_name-disk-[0-15].vhd - volume.setdefault( - "media_link", - kwargs["media_link"][:-4] + "-disk-{}.vhd".format(volume["lun"]), - ) - volume.setdefault( - "disk_label", kwargs["role_name"] + "-disk-{}".format(volume["lun"]) - ) - volume_dict = {"volume_name": volume["lun"], "disk_label": volume["disk_label"]} - - # Preparing the volume dict to be passed with ** - kwargs_add_data_disk = [ - "lun", - "host_caching", - "media_link", - "disk_label", - "disk_name", - "logical_disk_size_in_gb", - "source_media_link", - ] - for key in set(volume.keys()) - set(kwargs_add_data_disk): - del volume[key] - - result = conn.add_data_disk( - kwargs["service_name"], - kwargs["deployment_name"], - kwargs["role_name"], - **volume - ) - _wait_for_async(conn, result.request_id) - - msg = "{} attached to {} (aka {})".format( - volume_dict["volume_name"], kwargs["role_name"], name - ) - log.info(msg) - ret.append(msg) - return ret - - -# Helper function for azure tests -def _wait_for_async(conn, request_id): - """ - Helper function for azure tests - """ - count = 0 - log.debug("Waiting for asynchronous operation to complete") - result = conn.get_operation_status(request_id) - while result.status == "InProgress": - count = count + 1 - if count > 120: - raise ValueError( - "Timed out waiting for asynchronous operation to complete." - ) - time.sleep(5) - result = conn.get_operation_status(request_id) - - if result.status != "Succeeded": - raise AzureException( - "Operation failed. {message} ({code})".format( - message=result.error.message, code=result.error.code - ) - ) - - -@_deprecation_message -def destroy(name, conn=None, call=None, kwargs=None): - """ - Destroy a VM - - CLI Examples: - - .. code-block:: bash - - salt-cloud -d myminion - salt-cloud -a destroy myminion service_name=myservice - """ - if call == "function": - raise SaltCloudSystemExit( - "The destroy action must be called with -d, --destroy, -a or --action." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - instance_data = show_instance(name, call="action") - service_name = instance_data["deployment"]["name"] - disk_name = instance_data["role_info"]["os_virtual_hard_disk"]["disk_name"] - - ret = {} - # TODO: Add the ability to delete or not delete a hosted service when - # deleting a VM - try: - log.debug("Deleting role") - result = conn.delete_role(service_name, service_name, name) - delete_type = "delete_role" - except AzureException: - log.debug("Failed to delete role, deleting deployment") - try: - result = conn.delete_deployment(service_name, service_name) - except AzureConflictHttpError as exc: - log.error(exc.message) - raise SaltCloudSystemExit("{}: {}".format(name, exc.message)) - delete_type = "delete_deployment" - _wait_for_async(conn, result.request_id) - ret[name] = { - delete_type: {"request_id": result.request_id}, - } - if __opts__.get("update_cachedir", False) is True: - __utils__["cloud.delete_minion_cachedir"]( - name, _get_active_provider_name().split(":")[0], __opts__ - ) - - cleanup_disks = config.get_cloud_config_value( - "cleanup_disks", - get_configured_provider(), - __opts__, - search_global=False, - default=False, - ) - if cleanup_disks: - cleanup_vhds = kwargs.get( - "delete_vhd", - config.get_cloud_config_value( - "cleanup_vhds", - get_configured_provider(), - __opts__, - search_global=False, - default=False, - ), - ) - log.debug("Deleting disk %s", disk_name) - if cleanup_vhds: - log.debug("Deleting vhd") - - def wait_for_destroy(): - """ - Wait for the VM to be deleted - """ - try: - data = delete_disk( - kwargs={"name": disk_name, "delete_vhd": cleanup_vhds}, - call="function", - ) - return data - except AzureConflictHttpError: - log.debug("Waiting for VM to be destroyed...") - time.sleep(5) - return False - - data = salt.utils.cloud.wait_for_fun( - wait_for_destroy, - timeout=config.get_cloud_config_value( - "wait_for_fun_timeout", {}, __opts__, default=15 * 60 - ), - ) - ret[name]["delete_disk"] = { - "name": disk_name, - "delete_vhd": cleanup_vhds, - "data": data, - } - - # Services can't be cleaned up unless disks are too - cleanup_services = config.get_cloud_config_value( - "cleanup_services", - get_configured_provider(), - __opts__, - search_global=False, - default=False, - ) - if cleanup_services: - log.debug("Deleting service %s", service_name) - - def wait_for_disk_delete(): - """ - Wait for the disk to be deleted - """ - try: - data = delete_service( - kwargs={"name": service_name}, call="function" - ) - return data - except AzureConflictHttpError: - log.debug("Waiting for disk to be deleted...") - time.sleep(5) - return False - - data = salt.utils.cloud.wait_for_fun( - wait_for_disk_delete, - timeout=config.get_cloud_config_value( - "wait_for_fun_timeout", {}, __opts__, default=15 * 60 - ), - ) - ret[name]["delete_services"] = {"name": service_name, "data": data} - - return ret - - -@_deprecation_message -def list_storage_services(conn=None, call=None): - """ - List VMs on this Azure account, with full information - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_storage_services function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - ret = {} - accounts = conn.list_storage_accounts() - for service in accounts.storage_services: - ret[service.service_name] = { - "capabilities": service.capabilities, - "service_name": service.service_name, - "storage_service_properties": service.storage_service_properties, - "extended_properties": service.extended_properties, - "storage_service_keys": service.storage_service_keys, - "url": service.url, - } - return ret - - -@_deprecation_message -def get_operation_status(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Get Operation Status, based on a request ID - - CLI Example: - - .. code-block:: bash - - salt-cloud -f get_operation_status my-azure id=0123456789abcdef0123456789abcdef - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_instance function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "id" not in kwargs: - raise SaltCloudSystemExit('A request ID must be specified as "id"') - - if not conn: - conn = get_conn() - - data = conn.get_operation_status(kwargs["id"]) - ret = { - "http_status_code": data.http_status_code, - "id": kwargs["id"], - "status": data.status, - } - if hasattr(data.error, "code"): - ret["error"] = { - "code": data.error.code, - "message": data.error.message, - } - - return ret - - -@_deprecation_message -def list_storage(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List storage accounts associated with the account - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_storage my-azure - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_storage function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - data = conn.list_storage_accounts() - pprint.pprint(dir(data)) - ret = {} - for item in data.storage_services: - ret[item.service_name] = object_to_dict(item) - return ret - - -@_deprecation_message -def show_storage(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List storage service properties - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_storage my-azure name=my_storage - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_storage function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - data = conn.get_storage_account_properties( - kwargs["name"], - ) - return object_to_dict(data) - - -# To reflect the Azure API -get_storage = show_storage - - -@_deprecation_message -def show_storage_keys(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Show storage account keys - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_storage_keys my-azure name=my_storage - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_storage_keys function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - try: - data = conn.get_storage_account_keys( - kwargs["name"], - ) - except AzureMissingResourceHttpError as exc: - storage_data = show_storage(kwargs={"name": kwargs["name"]}, call="function") - if storage_data["storage_service_properties"]["status"] == "Creating": - raise SaltCloudSystemExit( - "The storage account keys have not yet been created." - ) - else: - raise SaltCloudSystemExit("{}: {}".format(kwargs["name"], exc.message)) - return object_to_dict(data) - - -# To reflect the Azure API -get_storage_keys = show_storage_keys - - -@_deprecation_message -def create_storage(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Create a new storage account - - CLI Example: - - .. code-block:: bash - - salt-cloud -f create_storage my-azure name=my_storage label=my_storage location='West US' - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_storage function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if not conn: - conn = get_conn() - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if "description" not in kwargs: - raise SaltCloudSystemExit('A description must be specified as "description"') - - if "label" not in kwargs: - raise SaltCloudSystemExit('A label must be specified as "label"') - - if "location" not in kwargs and "affinity_group" not in kwargs: - raise SaltCloudSystemExit( - "Either a location or an affinity_group must be specified (but not both)" - ) - - try: - data = conn.create_storage_account( - service_name=kwargs["name"], - label=kwargs["label"], - description=kwargs.get("description", None), - location=kwargs.get("location", None), - affinity_group=kwargs.get("affinity_group", None), - extended_properties=kwargs.get("extended_properties", None), - geo_replication_enabled=kwargs.get("geo_replication_enabled", None), - account_type=kwargs.get("account_type", "Standard_GRS"), - ) - return {"Success": "The storage account was successfully created"} - except AzureConflictHttpError: - raise SaltCloudSystemExit( - "There was a conflict. This usually means that the storage account already" - " exists." - ) - - -@_deprecation_message -def update_storage(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Update a storage account's properties - - CLI Example: - - .. code-block:: bash - - salt-cloud -f update_storage my-azure name=my_storage label=my_storage - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_storage function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - data = conn.update_storage_account( - service_name=kwargs["name"], - label=kwargs.get("label", None), - description=kwargs.get("description", None), - extended_properties=kwargs.get("extended_properties", None), - geo_replication_enabled=kwargs.get("geo_replication_enabled", None), - account_type=kwargs.get("account_type", "Standard_GRS"), - ) - return show_storage(kwargs={"name": kwargs["name"]}, call="function") - - -@_deprecation_message -def regenerate_storage_keys(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Regenerate storage account keys. Requires a key_type ("primary" or - "secondary") to be specified. - - CLI Example: - - .. code-block:: bash - - salt-cloud -f regenerate_storage_keys my-azure name=my_storage key_type=primary - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_storage function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if "key_type" not in kwargs or kwargs["key_type"] not in ("primary", "secondary"): - raise SaltCloudSystemExit( - 'A key_type must be specified ("primary" or "secondary")' - ) - - try: - data = conn.regenerate_storage_account_keys( - service_name=kwargs["name"], - key_type=kwargs["key_type"], - ) - return show_storage_keys(kwargs={"name": kwargs["name"]}, call="function") - except AzureConflictHttpError: - raise SaltCloudSystemExit( - "There was a conflict. This usually means that the storage account already" - " exists." - ) - - -@_deprecation_message -def delete_storage(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Delete a specific storage account - - CLI Examples: - - .. code-block:: bash - - salt-cloud -f delete_storage my-azure name=my_storage - """ - if call != "function": - raise SaltCloudSystemExit( - "The delete_storage function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if not conn: - conn = get_conn() - - try: - data = conn.delete_storage_account(kwargs["name"]) - return {"Success": "The storage account was successfully deleted"} - except AzureMissingResourceHttpError as exc: - raise SaltCloudSystemExit("{}: {}".format(kwargs["name"], exc.message)) - - -@_deprecation_message -def list_services(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List hosted services associated with the account - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_services my-azure - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_services function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - data = conn.list_hosted_services() - ret = {} - for item in data.hosted_services: - ret[item.service_name] = object_to_dict(item) - ret[item.service_name]["name"] = item.service_name - return ret - - -@_deprecation_message -def show_service(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List hosted service properties - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_service my-azure name=my_service - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_service function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - data = conn.get_hosted_service_properties( - kwargs["name"], kwargs.get("details", False) - ) - ret = object_to_dict(data) - return ret - - -@_deprecation_message -def create_service(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Create a new hosted service - - CLI Example: - - .. code-block:: bash - - salt-cloud -f create_service my-azure name=my_service label=my_service location='West US' - """ - if call != "function": - raise SaltCloudSystemExit( - "The create_service function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if "label" not in kwargs: - raise SaltCloudSystemExit('A label must be specified as "label"') - - if "location" not in kwargs and "affinity_group" not in kwargs: - raise SaltCloudSystemExit( - "Either a location or an affinity_group must be specified (but not both)" - ) - - try: - data = conn.create_hosted_service( - kwargs["name"], - kwargs["label"], - kwargs.get("description", None), - kwargs.get("location", None), - kwargs.get("affinity_group", None), - kwargs.get("extended_properties", None), - ) - return {"Success": "The service was successfully created"} - except AzureConflictHttpError: - raise SaltCloudSystemExit( - "There was a conflict. This usually means that the service already exists." - ) - - -@_deprecation_message -def delete_service(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Delete a specific service associated with the account - - CLI Examples: - - .. code-block:: bash - - salt-cloud -f delete_service my-azure name=my_service - """ - if call != "function": - raise SaltCloudSystemExit( - "The delete_service function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if not conn: - conn = get_conn() - - try: - conn.delete_hosted_service(kwargs["name"]) - return {"Success": "The service was successfully deleted"} - except AzureMissingResourceHttpError as exc: - raise SaltCloudSystemExit("{}: {}".format(kwargs["name"], exc.message)) - - -@_deprecation_message -def list_disks(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List disks associated with the account - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_disks my-azure - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_disks function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - data = conn.list_disks() - ret = {} - for item in data.disks: - ret[item.name] = object_to_dict(item) - return ret - - -@_deprecation_message -def show_disk(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Return information about a disk - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_disk my-azure name=my_disk - """ - if call != "function": - raise SaltCloudSystemExit( - "The get_disk function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - data = conn.get_disk(kwargs["name"]) - return object_to_dict(data) - - -# For consistency with Azure SDK -get_disk = show_disk - - -@_deprecation_message -def cleanup_unattached_disks(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Cleans up all disks associated with the account, which are not attached. - *** CAUTION *** This is a destructive function with no undo button, and no - "Are you sure?" confirmation! - - CLI Examples: - - .. code-block:: bash - - salt-cloud -f cleanup_unattached_disks my-azure name=my_disk - salt-cloud -f cleanup_unattached_disks my-azure name=my_disk delete_vhd=True - """ - if call != "function": - raise SaltCloudSystemExit( - "The delete_disk function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - disks = list_disks(kwargs=kwargs, conn=conn, call="function") - for disk in disks: - if disks[disk]["attached_to"] is None: - del_kwargs = { - "name": disks[disk]["name"], - "delete_vhd": kwargs.get("delete_vhd", False), - } - log.info( - "Deleting disk %s, deleting VHD: %s", - del_kwargs["name"], - del_kwargs["delete_vhd"], - ) - data = delete_disk(kwargs=del_kwargs, call="function") - return True - - -@_deprecation_message -def delete_disk(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Delete a specific disk associated with the account - - CLI Examples: - - .. code-block:: bash - - salt-cloud -f delete_disk my-azure name=my_disk - salt-cloud -f delete_disk my-azure name=my_disk delete_vhd=True - """ - if call != "function": - raise SaltCloudSystemExit( - "The delete_disk function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if not conn: - conn = get_conn() - - try: - data = conn.delete_disk(kwargs["name"], kwargs.get("delete_vhd", False)) - return {"Success": "The disk was successfully deleted"} - except AzureMissingResourceHttpError as exc: - raise SaltCloudSystemExit("{}: {}".format(kwargs["name"], exc.message)) - - -@_deprecation_message -def update_disk(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Update a disk's properties - - CLI Example: - - .. code-block:: bash - - salt-cloud -f update_disk my-azure name=my_disk label=my_disk - salt-cloud -f update_disk my-azure name=my_disk new_name=another_disk - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_disk function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - old_data = show_disk(kwargs={"name": kwargs["name"]}, call="function") - data = conn.update_disk( - disk_name=kwargs["name"], - has_operating_system=kwargs.get( - "has_operating_system", old_data["has_operating_system"] - ), - label=kwargs.get("label", old_data["label"]), - media_link=kwargs.get("media_link", old_data["media_link"]), - name=kwargs.get("new_name", old_data["name"]), - os=kwargs.get("os", old_data["os"]), - ) - return show_disk(kwargs={"name": kwargs["name"]}, call="function") - - -@_deprecation_message -def list_service_certificates(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List certificates associated with the service - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_service_certificates my-azure name=my_service - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_service_certificates function must be called with -f or" - " --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A service name must be specified as "name"') - - if not conn: - conn = get_conn() - - data = conn.list_service_certificates(service_name=kwargs["name"]) - ret = {} - for item in data.certificates: - ret[item.thumbprint] = object_to_dict(item) - return ret - - -@_deprecation_message -def show_service_certificate(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Return information about a service certificate - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_service_certificate my-azure name=my_service_certificate \\ - thumbalgorithm=sha1 thumbprint=0123456789ABCDEF - """ - if call != "function": - raise SaltCloudSystemExit( - "The get_service_certificate function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A service name must be specified as "name"') - - if "thumbalgorithm" not in kwargs: - raise SaltCloudSystemExit( - 'A thumbalgorithm must be specified as "thumbalgorithm"' - ) - - if "thumbprint" not in kwargs: - raise SaltCloudSystemExit('A thumbprint must be specified as "thumbprint"') - - data = conn.get_service_certificate( - kwargs["name"], - kwargs["thumbalgorithm"], - kwargs["thumbprint"], - ) - return object_to_dict(data) - - -# For consistency with Azure SDK -get_service_certificate = show_service_certificate - - -@_deprecation_message -def add_service_certificate(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Add a new service certificate - - CLI Example: - - .. code-block:: bash - - salt-cloud -f add_service_certificate my-azure name=my_service_certificate \\ - data='...CERT_DATA...' certificate_format=sha1 password=verybadpass - """ - if call != "function": - raise SaltCloudSystemExit( - "The add_service_certificate function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if "data" not in kwargs: - raise SaltCloudSystemExit('Certificate data must be specified as "data"') - - if "certificate_format" not in kwargs: - raise SaltCloudSystemExit( - 'A certificate_format must be specified as "certificate_format"' - ) - - if "password" not in kwargs: - raise SaltCloudSystemExit('A password must be specified as "password"') - - try: - data = conn.add_service_certificate( - kwargs["name"], - kwargs["data"], - kwargs["certificate_format"], - kwargs["password"], - ) - return {"Success": "The service certificate was successfully added"} - except AzureConflictHttpError: - raise SaltCloudSystemExit( - "There was a conflict. This usually means that the " - "service certificate already exists." - ) - - -@_deprecation_message -def delete_service_certificate(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Delete a specific certificate associated with the service - - CLI Examples: - - .. code-block:: bash - - salt-cloud -f delete_service_certificate my-azure name=my_service_certificate \\ - thumbalgorithm=sha1 thumbprint=0123456789ABCDEF - """ - if call != "function": - raise SaltCloudSystemExit( - "The delete_service_certificate function must be called with -f or" - " --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if "thumbalgorithm" not in kwargs: - raise SaltCloudSystemExit( - 'A thumbalgorithm must be specified as "thumbalgorithm"' - ) - - if "thumbprint" not in kwargs: - raise SaltCloudSystemExit('A thumbprint must be specified as "thumbprint"') - - if not conn: - conn = get_conn() - - try: - data = conn.delete_service_certificate( - kwargs["name"], - kwargs["thumbalgorithm"], - kwargs["thumbprint"], - ) - return {"Success": "The service certificate was successfully deleted"} - except AzureMissingResourceHttpError as exc: - raise SaltCloudSystemExit("{}: {}".format(kwargs["name"], exc.message)) - - -@_deprecation_message -def list_management_certificates(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List management certificates associated with the subscription - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_management_certificates my-azure name=my_management - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_management_certificates function must be called with -f or" - " --function." - ) - - if not conn: - conn = get_conn() - - data = conn.list_management_certificates() - ret = {} - for item in data.subscription_certificates: - ret[item.subscription_certificate_thumbprint] = object_to_dict(item) - return ret - - -@_deprecation_message -def show_management_certificate(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Return information about a management_certificate - - CLI Example: - - .. code-block:: bash - - salt-cloud -f get_management_certificate my-azure name=my_management_certificate \\ - thumbalgorithm=sha1 thumbprint=0123456789ABCDEF - """ - if call != "function": - raise SaltCloudSystemExit( - "The get_management_certificate function must be called with -f or" - " --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "thumbprint" not in kwargs: - raise SaltCloudSystemExit('A thumbprint must be specified as "thumbprint"') - - data = conn.get_management_certificate(kwargs["thumbprint"]) - return object_to_dict(data) - - -# For consistency with Azure SDK -get_management_certificate = show_management_certificate - - -@_deprecation_message -def add_management_certificate(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Add a new management certificate - - CLI Example: - - .. code-block:: bash - - salt-cloud -f add_management_certificate my-azure public_key='...PUBKEY...' \\ - thumbprint=0123456789ABCDEF data='...CERT_DATA...' - """ - if call != "function": - raise SaltCloudSystemExit( - "The add_management_certificate function must be called with -f or" - " --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "public_key" not in kwargs: - raise SaltCloudSystemExit('A public_key must be specified as "public_key"') - - if "thumbprint" not in kwargs: - raise SaltCloudSystemExit('A thumbprint must be specified as "thumbprint"') - - if "data" not in kwargs: - raise SaltCloudSystemExit('Certificate data must be specified as "data"') - - try: - conn.add_management_certificate( - kwargs["name"], - kwargs["thumbprint"], - kwargs["data"], - ) - return {"Success": "The management certificate was successfully added"} - except AzureConflictHttpError: - raise SaltCloudSystemExit( - "There was a conflict. " - "This usually means that the management certificate already exists." - ) - - -@_deprecation_message -def delete_management_certificate(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Delete a specific certificate associated with the management - - CLI Examples: - - .. code-block:: bash - - salt-cloud -f delete_management_certificate my-azure name=my_management_certificate \\ - thumbalgorithm=sha1 thumbprint=0123456789ABCDEF - """ - if call != "function": - raise SaltCloudSystemExit( - "The delete_management_certificate function must be called with -f or" - " --function." - ) - - if kwargs is None: - kwargs = {} - - if "thumbprint" not in kwargs: - raise SaltCloudSystemExit('A thumbprint must be specified as "thumbprint"') - - if not conn: - conn = get_conn() - - try: - conn.delete_management_certificate(kwargs["thumbprint"]) - return {"Success": "The management certificate was successfully deleted"} - except AzureMissingResourceHttpError as exc: - raise SaltCloudSystemExit("{}: {}".format(kwargs["thumbprint"], exc.message)) - - -@_deprecation_message -def list_virtual_networks(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List input endpoints associated with the deployment - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_virtual_networks my-azure service=myservice deployment=mydeployment - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_virtual_networks function must be called with -f or --function." - ) - - path = "services/networking/virtualnetwork" - data = query(path) - return data - - -@_deprecation_message -def list_input_endpoints(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List input endpoints associated with the deployment - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_input_endpoints my-azure service=myservice deployment=mydeployment - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_input_endpoints function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "service" not in kwargs: - raise SaltCloudSystemExit('A service name must be specified as "service"') - - if "deployment" not in kwargs: - raise SaltCloudSystemExit('A deployment name must be specified as "deployment"') - - path = "services/hostedservices/{}/deployments/{}".format( - kwargs["service"], - kwargs["deployment"], - ) - - data = query(path) - if data is None: - raise SaltCloudSystemExit( - "There was an error listing endpoints with the {} service on the {}" - " deployment.".format(kwargs["service"], kwargs["deployment"]) - ) - - ret = {} - for item in data: - if "Role" in item: - role = item["Role"] - if not isinstance(role, dict): - return ret - input_endpoint = ( - role["ConfigurationSets"]["ConfigurationSet"] - .get("InputEndpoints", {}) - .get("InputEndpoint") - ) - if not input_endpoint: - continue - if not isinstance(input_endpoint, list): - input_endpoint = [input_endpoint] - for endpoint in input_endpoint: - ret[endpoint["Name"]] = endpoint - return ret - return ret - - -@_deprecation_message -def show_input_endpoint(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Show an input endpoint associated with the deployment - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_input_endpoint my-azure service=myservice \\ - deployment=mydeployment name=SSH - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_input_endpoint function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('An endpoint name must be specified as "name"') - - data = list_input_endpoints(kwargs=kwargs, call="function") - return data.get(kwargs["name"], None) - - -# For consistency with Azure SDK -get_input_endpoint = show_input_endpoint - - -@_deprecation_message -def update_input_endpoint(kwargs=None, conn=None, call=None, activity="update"): - """ - .. versionadded:: 2015.8.0 - - Update an input endpoint associated with the deployment. Please note that - there may be a delay before the changes show up. - - CLI Example: - - .. code-block:: bash - - salt-cloud -f update_input_endpoint my-azure service=myservice \\ - deployment=mydeployment role=myrole name=HTTP local_port=80 \\ - port=80 protocol=tcp enable_direct_server_return=False \\ - timeout_for_tcp_idle_connection=4 - """ - if call != "function": - raise SaltCloudSystemExit( - "The update_input_endpoint function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "service" not in kwargs: - raise SaltCloudSystemExit('A service name must be specified as "service"') - - if "deployment" not in kwargs: - raise SaltCloudSystemExit('A deployment name must be specified as "deployment"') - - if "name" not in kwargs: - raise SaltCloudSystemExit('An endpoint name must be specified as "name"') - - if "role" not in kwargs: - raise SaltCloudSystemExit('An role name must be specified as "role"') - - if activity != "delete": - if "port" not in kwargs: - raise SaltCloudSystemExit('An endpoint port must be specified as "port"') - - if "protocol" not in kwargs: - raise SaltCloudSystemExit( - 'An endpoint protocol (tcp or udp) must be specified as "protocol"' - ) - - if "local_port" not in kwargs: - kwargs["local_port"] = kwargs["port"] - - if "enable_direct_server_return" not in kwargs: - kwargs["enable_direct_server_return"] = False - kwargs["enable_direct_server_return"] = str( - kwargs["enable_direct_server_return"] - ).lower() - - if "timeout_for_tcp_idle_connection" not in kwargs: - kwargs["timeout_for_tcp_idle_connection"] = 4 - - old_endpoints = list_input_endpoints(kwargs, call="function") - - endpoints_xml = "" - endpoint_xml = """ - - {local_port} - {name} - {port} - {protocol} - {enable_direct_server_return} - {timeout_for_tcp_idle_connection} - """ - - if activity == "add": - old_endpoints[kwargs["name"]] = kwargs - old_endpoints[kwargs["name"]]["Name"] = kwargs["name"] - - for endpoint in old_endpoints: - if old_endpoints[endpoint]["Name"] == kwargs["name"]: - if activity != "delete": - this_endpoint_xml = endpoint_xml.format(**kwargs) - endpoints_xml += this_endpoint_xml - else: - this_endpoint_xml = endpoint_xml.format( - local_port=old_endpoints[endpoint]["LocalPort"], - name=old_endpoints[endpoint]["Name"], - port=old_endpoints[endpoint]["Port"], - protocol=old_endpoints[endpoint]["Protocol"], - enable_direct_server_return=old_endpoints[endpoint][ - "EnableDirectServerReturn" - ], - timeout_for_tcp_idle_connection=old_endpoints[endpoint].get( - "IdleTimeoutInMinutes", 4 - ), - ) - endpoints_xml += this_endpoint_xml - - request_xml = """ - - - NetworkConfiguration - {} - - - - - -""".format( - endpoints_xml - ) - - path = "services/hostedservices/{}/deployments/{}/roles/{}".format( - kwargs["service"], - kwargs["deployment"], - kwargs["role"], - ) - query( - path=path, - method="PUT", - header_dict={"Content-Type": "application/xml"}, - data=request_xml, - decode=False, - ) - return True - - -@_deprecation_message -def add_input_endpoint(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Add an input endpoint to the deployment. Please note that - there may be a delay before the changes show up. - - CLI Example: - - .. code-block:: bash - - salt-cloud -f add_input_endpoint my-azure service=myservice \\ - deployment=mydeployment role=myrole name=HTTP local_port=80 \\ - port=80 protocol=tcp enable_direct_server_return=False \\ - timeout_for_tcp_idle_connection=4 - """ - return update_input_endpoint( - kwargs=kwargs, - conn=conn, - call="function", - activity="add", - ) - - -@_deprecation_message -def delete_input_endpoint(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Delete an input endpoint from the deployment. Please note that - there may be a delay before the changes show up. - - CLI Example: - - .. code-block:: bash - - salt-cloud -f delete_input_endpoint my-azure service=myservice \\ - deployment=mydeployment role=myrole name=HTTP - """ - return update_input_endpoint( - kwargs=kwargs, - conn=conn, - call="function", - activity="delete", - ) - - -@_deprecation_message -def show_deployment(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Return information about a deployment - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_deployment my-azure name=my_deployment - """ - if call != "function": - raise SaltCloudSystemExit( - "The get_deployment function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "service_name" not in kwargs: - raise SaltCloudSystemExit('A service name must be specified as "service_name"') - - if "deployment_name" not in kwargs: - raise SaltCloudSystemExit( - 'A deployment name must be specified as "deployment_name"' - ) - - data = conn.get_deployment_by_name( - service_name=kwargs["service_name"], - deployment_name=kwargs["deployment_name"], - ) - return object_to_dict(data) - - -# For consistency with Azure SDK -get_deployment = show_deployment - - -@_deprecation_message -def list_affinity_groups(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List input endpoints associated with the deployment - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_affinity_groups my-azure - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_affinity_groups function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - data = conn.list_affinity_groups() - ret = {} - for item in data.affinity_groups: - ret[item.name] = object_to_dict(item) - return ret - - -@_deprecation_message -def show_affinity_group(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Show an affinity group associated with the account - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_affinity_group my-azure service=myservice \\ - deployment=mydeployment name=SSH - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_affinity_group function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('An affinity group name must be specified as "name"') - - data = conn.get_affinity_group_properties(affinity_group_name=kwargs["name"]) - return object_to_dict(data) - - -# For consistency with Azure SDK -get_affinity_group = show_affinity_group - - -@_deprecation_message -def create_affinity_group(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Create a new affinity group - - CLI Example: - - .. code-block:: bash - - salt-cloud -f create_affinity_group my-azure name=my_affinity_group - """ - if call != "function": - raise SaltCloudSystemExit( - "The create_affinity_group function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if "label" not in kwargs: - raise SaltCloudSystemExit('A label must be specified as "label"') - - if "location" not in kwargs: - raise SaltCloudSystemExit('A location must be specified as "location"') - - try: - conn.create_affinity_group( - kwargs["name"], - kwargs["label"], - kwargs["location"], - kwargs.get("description", None), - ) - return {"Success": "The affinity group was successfully created"} - except AzureConflictHttpError: - raise SaltCloudSystemExit( - "There was a conflict. This usually means that the affinity group already" - " exists." - ) - - -@_deprecation_message -def update_affinity_group(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Update an affinity group's properties - - CLI Example: - - .. code-block:: bash - - salt-cloud -f update_affinity_group my-azure name=my_group label=my_group - """ - if call != "function": - raise SaltCloudSystemExit( - "The update_affinity_group function must be called with -f or --function." - ) - - if not conn: - conn = get_conn() - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if "label" not in kwargs: - raise SaltCloudSystemExit('A label must be specified as "label"') - - conn.update_affinity_group( - affinity_group_name=kwargs["name"], - label=kwargs["label"], - description=kwargs.get("description", None), - ) - return show_affinity_group(kwargs={"name": kwargs["name"]}, call="function") - - -@_deprecation_message -def delete_affinity_group(kwargs=None, conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Delete a specific affinity group associated with the account - - CLI Examples: - - .. code-block:: bash - - salt-cloud -f delete_affinity_group my-azure name=my_affinity_group - """ - if call != "function": - raise SaltCloudSystemExit( - "The delete_affinity_group function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit('A name must be specified as "name"') - - if not conn: - conn = get_conn() - - try: - conn.delete_affinity_group(kwargs["name"]) - return {"Success": "The affinity group was successfully deleted"} - except AzureMissingResourceHttpError as exc: - raise SaltCloudSystemExit("{}: {}".format(kwargs["name"], exc.message)) - - -@_deprecation_message -def get_storage_conn(storage_account=None, storage_key=None, conn_kwargs=None): - """ - .. versionadded:: 2015.8.0 - - Return a storage_conn object for the storage account - """ - if conn_kwargs is None: - conn_kwargs = {} - - if not storage_account: - storage_account = config.get_cloud_config_value( - "storage_account", - get_configured_provider(), - __opts__, - search_global=False, - default=conn_kwargs.get("storage_account", None), - ) - if not storage_key: - storage_key = config.get_cloud_config_value( - "storage_key", - get_configured_provider(), - __opts__, - search_global=False, - default=conn_kwargs.get("storage_key", None), - ) - return azure.storage.BlobService(storage_account, storage_key) - - -@_deprecation_message -def make_blob_url(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Creates the URL to access a blob - - CLI Example: - - .. code-block:: bash - - salt-cloud -f make_blob_url my-azure container=mycontainer blob=myblob - - container: - Name of the container. - blob: - Name of the blob. - account: - Name of the storage account. If not specified, derives the host base - from the provider configuration. - protocol: - Protocol to use: 'http' or 'https'. If not specified, derives the host - base from the provider configuration. - host_base: - Live host base URL. If not specified, derives the host base from the - provider configuration. - """ - if call != "function": - raise SaltCloudSystemExit( - "The make_blob_url function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "container" not in kwargs: - raise SaltCloudSystemExit('A container name must be specified as "container"') - - if "blob" not in kwargs: - raise SaltCloudSystemExit('A blob name must be specified as "blob"') - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.make_blob_url( - kwargs["container"], - kwargs["blob"], - kwargs.get("account", None), - kwargs.get("protocol", None), - kwargs.get("host_base", None), - ) - ret = {} - for item in data.containers: - ret[item.name] = object_to_dict(item) - return ret - - -@_deprecation_message -def list_storage_containers(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List containers associated with the storage account - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_storage_containers my-azure - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_storage_containers function must be called with -f or --function." - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.list_containers() - ret = {} - for item in data.containers: - ret[item.name] = object_to_dict(item) - return ret - - -@_deprecation_message -def create_storage_container(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Create a storage container - - CLI Example: - - .. code-block:: bash - - salt-cloud -f create_storage_container my-azure name=mycontainer - - name: - Name of container to create. - meta_name_values: - Optional. A dict with name_value pairs to associate with the - container as metadata. Example:{'Category':'test'} - blob_public_access: - Optional. Possible values include: container, blob - fail_on_exist: - Specify whether to throw an exception when the container exists. - """ - if call != "function": - raise SaltCloudSystemExit( - "The create_storage_container function must be called with -f or" - " --function." - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - try: - storage_conn.create_container( - container_name=kwargs["name"], - x_ms_meta_name_values=kwargs.get("meta_name_values", None), - x_ms_blob_public_access=kwargs.get("blob_public_access", None), - fail_on_exist=kwargs.get("fail_on_exist", False), - ) - return {"Success": "The storage container was successfully created"} - except AzureConflictHttpError: - raise SaltCloudSystemExit( - "There was a conflict. This usually means that the storage container" - " already exists." - ) - - -@_deprecation_message -def show_storage_container(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Show a container associated with the storage account - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_storage_container my-azure name=myservice - - name: - Name of container to show. - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_storage_container function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit( - 'An storage container name must be specified as "name"' - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.get_container_properties( - container_name=kwargs["name"], - x_ms_lease_id=kwargs.get("lease_id", None), - ) - return data - - -# For consistency with Azure SDK -get_storage_container = show_storage_container - - -@_deprecation_message -def show_storage_container_metadata(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Show a storage container's metadata - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_storage_container_metadata my-azure name=myservice - - name: - Name of container to show. - lease_id: - If specified, show_storage_container_metadata only succeeds if the - container's lease is active and matches this ID. - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_storage_container function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit( - 'An storage container name must be specified as "name"' - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.get_container_metadata( - container_name=kwargs["name"], - x_ms_lease_id=kwargs.get("lease_id", None), - ) - return data - - -# For consistency with Azure SDK -get_storage_container_metadata = show_storage_container_metadata - - -@_deprecation_message -def set_storage_container_metadata(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Set a storage container's metadata - - CLI Example: - - .. code-block:: bash - - salt-cloud -f set_storage_container my-azure name=mycontainer \\ - x_ms_meta_name_values='{"my_name": "my_value"}' - - name: - Name of existing container. - meta_name_values: - A dict containing name, value for metadata. - Example: {'category':'test'} - lease_id: - If specified, set_storage_container_metadata only succeeds if the - container's lease is active and matches this ID. - """ - if call != "function": - raise SaltCloudSystemExit( - "The create_storage_container function must be called with -f or" - " --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit( - 'An storage container name must be specified as "name"' - ) - - x_ms_meta_name_values = salt.utils.yaml.safe_load( - kwargs.get("meta_name_values", "") - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - try: - storage_conn.set_container_metadata( - container_name=kwargs["name"], - x_ms_meta_name_values=x_ms_meta_name_values, - x_ms_lease_id=kwargs.get("lease_id", None), - ) - return {"Success": "The storage container was successfully updated"} - except AzureConflictHttpError: - raise SaltCloudSystemExit("There was a conflict.") - - -@_deprecation_message -def show_storage_container_acl(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Show a storage container's acl - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_storage_container_acl my-azure name=myservice - - name: - Name of existing container. - lease_id: - If specified, show_storage_container_acl only succeeds if the - container's lease is active and matches this ID. - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_storage_container function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit( - 'An storage container name must be specified as "name"' - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.get_container_acl( - container_name=kwargs["name"], - x_ms_lease_id=kwargs.get("lease_id", None), - ) - return data - - -# For consistency with Azure SDK -get_storage_container_acl = show_storage_container_acl - - -@_deprecation_message -def set_storage_container_acl(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Set a storage container's acl - - CLI Example: - - .. code-block:: bash - - salt-cloud -f set_storage_container my-azure name=mycontainer - - name: - Name of existing container. - signed_identifiers: - SignedIdentifers instance - blob_public_access: - Optional. Possible values include: container, blob - lease_id: - If specified, set_storage_container_acl only succeeds if the - container's lease is active and matches this ID. - """ - if call != "function": - raise SaltCloudSystemExit( - "The create_storage_container function must be called with -f or" - " --function." - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - try: - data = storage_conn.set_container_acl( - container_name=kwargs["name"], - signed_identifiers=kwargs.get("signed_identifiers", None), - x_ms_blob_public_access=kwargs.get("blob_public_access", None), - x_ms_lease_id=kwargs.get("lease_id", None), - ) - return {"Success": "The storage container was successfully updated"} - except AzureConflictHttpError: - raise SaltCloudSystemExit("There was a conflict.") - - -@_deprecation_message -def delete_storage_container(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Delete a container associated with the storage account - - CLI Example: - - .. code-block:: bash - - salt-cloud -f delete_storage_container my-azure name=mycontainer - - name: - Name of container to create. - fail_not_exist: - Specify whether to throw an exception when the container exists. - lease_id: - If specified, delete_storage_container only succeeds if the - container's lease is active and matches this ID. - """ - if call != "function": - raise SaltCloudSystemExit( - "The delete_storage_container function must be called with -f or" - " --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit( - 'An storage container name must be specified as "name"' - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.delete_container( - container_name=kwargs["name"], - fail_not_exist=kwargs.get("fail_not_exist", None), - x_ms_lease_id=kwargs.get("lease_id", None), - ) - return data - - -@_deprecation_message -def lease_storage_container(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Lease a container associated with the storage account - - CLI Example: - - .. code-block:: bash - - salt-cloud -f lease_storage_container my-azure name=mycontainer - - name: - Name of container to create. - lease_action: - Required. Possible values: acquire|renew|release|break|change - lease_id: - Required if the container has an active lease. - lease_duration: - Specifies the duration of the lease, in seconds, or negative one - (-1) for a lease that never expires. A non-infinite lease can be - between 15 and 60 seconds. A lease duration cannot be changed - using renew or change. For backwards compatibility, the default is - 60, and the value is only used on an acquire operation. - lease_break_period: - Optional. For a break operation, this is the proposed duration of - seconds that the lease should continue before it is broken, between - 0 and 60 seconds. This break period is only used if it is shorter - than the time remaining on the lease. If longer, the time remaining - on the lease is used. A new lease will not be available before the - break period has expired, but the lease may be held for longer than - the break period. If this header does not appear with a break - operation, a fixed-duration lease breaks after the remaining lease - period elapses, and an infinite lease breaks immediately. - proposed_lease_id: - Optional for acquire, required for change. Proposed lease ID, in a - GUID string format. - """ - if call != "function": - raise SaltCloudSystemExit( - "The lease_storage_container function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "name" not in kwargs: - raise SaltCloudSystemExit( - 'An storage container name must be specified as "name"' - ) - - lease_actions = ("acquire", "renew", "release", "break", "change") - - if kwargs.get("lease_action", None) not in lease_actions: - raise SaltCloudSystemExit( - "A lease_action must be one of: {}".format(", ".join(lease_actions)) - ) - - if kwargs["lease_action"] != "acquire" and "lease_id" not in kwargs: - raise SaltCloudSystemExit( - 'A lease ID must be specified for the "{}" lease action ' - 'as "lease_id"'.format(kwargs["lease_action"]) - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.lease_container( - container_name=kwargs["name"], - x_ms_lease_action=kwargs["lease_action"], - x_ms_lease_id=kwargs.get("lease_id", None), - x_ms_lease_duration=kwargs.get("lease_duration", 60), - x_ms_lease_break_period=kwargs.get("lease_break_period", None), - x_ms_proposed_lease_id=kwargs.get("proposed_lease_id", None), - ) - - return data - - -@_deprecation_message -def list_blobs(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - List blobs associated with the container - - CLI Example: - - .. code-block:: bash - - salt-cloud -f list_blobs my-azure container=mycontainer - - container: - The name of the storage container - prefix: - Optional. Filters the results to return only blobs whose names - begin with the specified prefix. - marker: - Optional. A string value that identifies the portion of the list - to be returned with the next list operation. The operation returns - a marker value within the response body if the list returned was - not complete. The marker value may then be used in a subsequent - call to request the next set of list items. The marker value is - opaque to the client. - maxresults: - Optional. Specifies the maximum number of blobs to return, - including all BlobPrefix elements. If the request does not specify - maxresults or specifies a value greater than 5,000, the server will - return up to 5,000 items. Setting maxresults to a value less than - or equal to zero results in error response code 400 (Bad Request). - include: - Optional. Specifies one or more datasets to include in the - response. To specify more than one of these options on the URI, - you must separate each option with a comma. Valid values are: - - snapshots: - Specifies that snapshots should be included in the - enumeration. Snapshots are listed from oldest to newest in - the response. - metadata: - Specifies that blob metadata be returned in the response. - uncommittedblobs: - Specifies that blobs for which blocks have been uploaded, - but which have not been committed using Put Block List - (REST API), be included in the response. - copy: - Version 2012-02-12 and newer. Specifies that metadata - related to any current or previous Copy Blob operation - should be included in the response. - delimiter: - Optional. When the request includes this parameter, the operation - returns a BlobPrefix element in the response body that acts as a - placeholder for all blobs whose names begin with the same - substring up to the appearance of the delimiter character. The - delimiter may be a single character or a string. - """ - if call != "function": - raise SaltCloudSystemExit( - "The list_blobs function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "container" not in kwargs: - raise SaltCloudSystemExit( - 'An storage container name must be specified as "container"' - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - return salt.utils.msazure.list_blobs(storage_conn=storage_conn, **kwargs) - - -@_deprecation_message -def show_blob_service_properties(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Show a blob's service properties - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_blob_service_properties my-azure - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_blob_service_properties function must be called with -f or" - " --function." - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.get_blob_service_properties( - timeout=kwargs.get("timeout", None), - ) - return data - - -# For consistency with Azure SDK -get_blob_service_properties = show_blob_service_properties - - -@_deprecation_message -def set_blob_service_properties(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Sets the properties of a storage account's Blob service, including - Windows Azure Storage Analytics. You can also use this operation to - set the default request version for all incoming requests that do not - have a version specified. - - CLI Example: - - .. code-block:: bash - - salt-cloud -f set_blob_service_properties my-azure - - properties: - a StorageServiceProperties object. - timeout: - Optional. The timeout parameter is expressed in seconds. - """ - if call != "function": - raise SaltCloudSystemExit( - "The set_blob_service_properties function must be called with -f or" - " --function." - ) - - if kwargs is None: - kwargs = {} - - if "properties" not in kwargs: - raise SaltCloudSystemExit( - 'The blob service properties name must be specified as "properties"' - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.get_blob_service_properties( - storage_service_properties=kwargs["properties"], - timeout=kwargs.get("timeout", None), - ) - return data - - -@_deprecation_message -def show_blob_properties(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Returns all user-defined metadata, standard HTTP properties, and - system properties for the blob. - - CLI Example: - - .. code-block:: bash - - salt-cloud -f show_blob_properties my-azure container=mycontainer blob=myblob - - container: - Name of existing container. - blob: - Name of existing blob. - lease_id: - Required if the blob has an active lease. - """ - if call != "function": - raise SaltCloudSystemExit( - "The show_blob_properties function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "container" not in kwargs: - raise SaltCloudSystemExit('The container name must be specified as "container"') - - if "blob" not in kwargs: - raise SaltCloudSystemExit('The blob name must be specified as "blob"') - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - try: - data = storage_conn.get_blob_properties( - container_name=kwargs["container"], - blob_name=kwargs["blob"], - x_ms_lease_id=kwargs.get("lease_id", None), - ) - except AzureMissingResourceHttpError: - raise SaltCloudSystemExit("The specified blob does not exist.") - - return data - - -# For consistency with Azure SDK -get_blob_properties = show_blob_properties - - -@_deprecation_message -def set_blob_properties(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Set a blob's properties - - CLI Example: - - .. code-block:: bash - - salt-cloud -f set_blob_properties my-azure - - container: - Name of existing container. - blob: - Name of existing blob. - blob_cache_control: - Optional. Modifies the cache control string for the blob. - blob_content_type: - Optional. Sets the blob's content type. - blob_content_md5: - Optional. Sets the blob's MD5 hash. - blob_content_encoding: - Optional. Sets the blob's content encoding. - blob_content_language: - Optional. Sets the blob's content language. - lease_id: - Required if the blob has an active lease. - blob_content_disposition: - Optional. Sets the blob's Content-Disposition header. - The Content-Disposition response header field conveys additional - information about how to process the response payload, and also can - be used to attach additional metadata. For example, if set to - attachment, it indicates that the user-agent should not display the - response, but instead show a Save As dialog with a filename other - than the blob name specified. - """ - if call != "function": - raise SaltCloudSystemExit( - "The set_blob_properties function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "container" not in kwargs: - raise SaltCloudSystemExit( - 'The blob container name must be specified as "container"' - ) - - if "blob" not in kwargs: - raise SaltCloudSystemExit('The blob name must be specified as "blob"') - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - data = storage_conn.get_blob_properties( - container_name=kwargs["container"], - blob_name=kwargs["blob"], - x_ms_blob_cache_control=kwargs.get("blob_cache_control", None), - x_ms_blob_content_type=kwargs.get("blob_content_type", None), - x_ms_blob_content_md5=kwargs.get("blob_content_md5", None), - x_ms_blob_content_encoding=kwargs.get("blob_content_encoding", None), - x_ms_blob_content_language=kwargs.get("blob_content_language", None), - x_ms_lease_id=kwargs.get("lease_id", None), - x_ms_blob_content_disposition=kwargs.get("blob_content_disposition", None), - ) - - return data - - -@_deprecation_message -def put_blob(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Upload a blob - - CLI Examples: - - .. code-block:: bash - - salt-cloud -f put_blob my-azure container=base name=top.sls blob_path=/srv/salt/top.sls - salt-cloud -f put_blob my-azure container=base name=content.txt blob_content='Some content' - - container: - Name of existing container. - name: - Name of existing blob. - blob_path: - The path on the local machine of the file to upload as a blob. Either - this or blob_content must be specified. - blob_content: - The actual content to be uploaded as a blob. Either this or blob_path - must me specified. - cache_control: - Optional. The Blob service stores this value but does not use or - modify it. - content_language: - Optional. Specifies the natural languages used by this resource. - content_md5: - Optional. An MD5 hash of the blob content. This hash is used to - verify the integrity of the blob during transport. When this header - is specified, the storage service checks the hash that has arrived - with the one that was sent. If the two hashes do not match, the - operation will fail with error code 400 (Bad Request). - blob_content_type: - Optional. Set the blob's content type. - blob_content_encoding: - Optional. Set the blob's content encoding. - blob_content_language: - Optional. Set the blob's content language. - blob_content_md5: - Optional. Set the blob's MD5 hash. - blob_cache_control: - Optional. Sets the blob's cache control. - meta_name_values: - A dict containing name, value for metadata. - lease_id: - Required if the blob has an active lease. - """ - if call != "function": - raise SaltCloudSystemExit( - "The put_blob function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "container" not in kwargs: - raise SaltCloudSystemExit( - 'The blob container name must be specified as "container"' - ) - - if "name" not in kwargs: - raise SaltCloudSystemExit('The blob name must be specified as "name"') - - if "blob_path" not in kwargs and "blob_content" not in kwargs: - raise SaltCloudSystemExit( - 'Either a path to a file needs to be passed in as "blob_path" or ' - 'the contents of a blob as "blob_content."' - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - return salt.utils.msazure.put_blob(storage_conn=storage_conn, **kwargs) - - -@_deprecation_message -def get_blob(kwargs=None, storage_conn=None, call=None): - """ - .. versionadded:: 2015.8.0 - - Download a blob - - CLI Example: - - .. code-block:: bash - - salt-cloud -f get_blob my-azure container=base name=top.sls local_path=/srv/salt/top.sls - salt-cloud -f get_blob my-azure container=base name=content.txt return_content=True - - container: - Name of existing container. - name: - Name of existing blob. - local_path: - The path on the local machine to download the blob to. Either this or - return_content must be specified. - return_content: - Whether or not to return the content directly from the blob. If - specified, must be True or False. Either this or the local_path must - be specified. - snapshot: - Optional. The snapshot parameter is an opaque DateTime value that, - when present, specifies the blob snapshot to retrieve. - lease_id: - Required if the blob has an active lease. - progress_callback: - callback for progress with signature function(current, total) where - current is the number of bytes transferred so far, and total is the - size of the blob. - max_connections: - Maximum number of parallel connections to use when the blob size - exceeds 64MB. - Set to 1 to download the blob chunks sequentially. - Set to 2 or more to download the blob chunks in parallel. This uses - more system resources but will download faster. - max_retries: - Number of times to retry download of blob chunk if an error occurs. - retry_wait: - Sleep time in secs between retries. - """ - if call != "function": - raise SaltCloudSystemExit( - "The get_blob function must be called with -f or --function." - ) - - if kwargs is None: - kwargs = {} - - if "container" not in kwargs: - raise SaltCloudSystemExit( - 'The blob container name must be specified as "container"' - ) - - if "name" not in kwargs: - raise SaltCloudSystemExit('The blob name must be specified as "name"') - - if "local_path" not in kwargs and "return_content" not in kwargs: - raise SaltCloudSystemExit( - 'Either a local path needs to be passed in as "local_path" or ' - '"return_content" to return the blob contents directly' - ) - - if not storage_conn: - storage_conn = get_storage_conn(conn_kwargs=kwargs) - - return salt.utils.msazure.get_blob(storage_conn=storage_conn, **kwargs) - - -@_deprecation_message -def query(path, method="GET", data=None, params=None, header_dict=None, decode=True): - """ - Perform a query directly against the Azure REST API - """ - certificate_path = config.get_cloud_config_value( - "certificate_path", get_configured_provider(), __opts__, search_global=False - ) - subscription_id = salt.utils.stringutils.to_str( - config.get_cloud_config_value( - "subscription_id", get_configured_provider(), __opts__, search_global=False - ) - ) - management_host = config.get_cloud_config_value( - "management_host", - get_configured_provider(), - __opts__, - search_global=False, - default="management.core.windows.net", - ) - backend = config.get_cloud_config_value( - "backend", get_configured_provider(), __opts__, search_global=False - ) - url = "https://{management_host}/{subscription_id}/{path}".format( - management_host=management_host, - subscription_id=subscription_id, - path=path, - ) - - if header_dict is None: - header_dict = {} - - header_dict["x-ms-version"] = "2014-06-01" - - result = salt.utils.http.query( - url, - method=method, - params=params, - data=data, - header_dict=header_dict, - port=443, - text=True, - cert=certificate_path, - backend=backend, - decode=decode, - decode_type="xml", - ) - if "dict" in result: - return result["dict"] - return diff --git a/salt/fileserver/azurefs.py b/salt/fileserver/azurefs.py deleted file mode 100644 index cdb1a390d7a..00000000000 --- a/salt/fileserver/azurefs.py +++ /dev/null @@ -1,396 +0,0 @@ -""" -The backend for serving files from the Azure blob storage service. - -.. versionadded:: 2015.8.0 - -To enable, add ``azurefs`` to the :conf_master:`fileserver_backend` option in -the Master config file. - -.. code-block:: yaml - - fileserver_backend: - - azurefs - -Starting in Salt 2018.3.0, this fileserver requires the standalone Azure -Storage SDK for Python. Theoretically any version >= v0.20.0 should work, but -it was developed against the v0.33.0 version. - -Each storage container will be mapped to an environment. By default, containers -will be mapped to the ``base`` environment. You can override this behavior with -the ``saltenv`` configuration option. You can have an unlimited number of -storage containers, and can have a storage container serve multiple -environments, or have multiple storage containers mapped to the same -environment. Normal first-found rules apply, and storage containers are -searched in the order they are defined. - -You must have either an account_key or a sas_token defined for each container, -if it is private. If you use a sas_token, it must have READ and LIST -permissions. - -.. code-block:: yaml - - azurefs: - - account_name: my_storage - account_key: 'fNH9cRp0+qVIVYZ+5rnZAhHc9ycOUcJnHtzpfOr0W0sxrtL2KVLuMe1xDfLwmfed+JJInZaEdWVCPHD4d/oqeA==' - container_name: my_container - - account_name: my_storage - sas_token: 'ss=b&sp=&sv=2015-07-08&sig=cohxXabx8FQdXsSEHyUXMjsSfNH2tZ2OB97Ou44pkRE%3D&srt=co&se=2017-04-18T21%3A38%3A01Z' - container_name: my_dev_container - saltenv: dev - - account_name: my_storage - container_name: my_public_container - -.. note:: - - Do not include the leading ? for sas_token if generated from the web -""" - - -import base64 -import logging -import os -import shutil - -import salt.fileserver -import salt.utils.files -import salt.utils.gzip_util -import salt.utils.hashutils -import salt.utils.json -import salt.utils.path -import salt.utils.stringutils -from salt.utils.versions import Version - -try: - import azure.storage - - if Version(azure.storage.__version__) < Version("0.20.0"): - raise ImportError("azure.storage.__version__ must be >= 0.20.0") - HAS_AZURE = True -except (ImportError, AttributeError): - HAS_AZURE = False - - -__virtualname__ = "azurefs" - -log = logging.getLogger() - - -def __virtual__(): - """ - Only load if defined in fileserver_backend and azure.storage is present - """ - if __virtualname__ not in __opts__["fileserver_backend"]: - return False - - if not HAS_AZURE: - return False - - if "azurefs" not in __opts__: - return False - - if not _validate_config(): - return False - - return True - - -def find_file(path, saltenv="base", **kwargs): - """ - Search the environment for the relative path - """ - fnd = {"path": "", "rel": ""} - for container in __opts__.get("azurefs", []): - if container.get("saltenv", "base") != saltenv: - continue - full = os.path.join(_get_container_path(container), path) - if os.path.isfile(full) and not salt.fileserver.is_file_ignored(__opts__, path): - fnd["path"] = full - fnd["rel"] = path - try: - # Converting the stat result to a list, the elements of the - # list correspond to the following stat_result params: - # 0 => st_mode=33188 - # 1 => st_ino=10227377 - # 2 => st_dev=65026 - # 3 => st_nlink=1 - # 4 => st_uid=1000 - # 5 => st_gid=1000 - # 6 => st_size=1056233 - # 7 => st_atime=1468284229 - # 8 => st_mtime=1456338235 - # 9 => st_ctime=1456338235 - fnd["stat"] = list(os.stat(full)) - except Exception: # pylint: disable=broad-except - pass - return fnd - return fnd - - -def envs(): - """ - Each container configuration can have an environment setting, or defaults - to base - """ - saltenvs = [] - for container in __opts__.get("azurefs", []): - saltenvs.append(container.get("saltenv", "base")) - # Remove duplicates - return list(set(saltenvs)) - - -def serve_file(load, fnd): - """ - Return a chunk from a file based on the data received - """ - ret = {"data": "", "dest": ""} - required_load_keys = ("path", "loc", "saltenv") - if not all(x in load for x in required_load_keys): - log.debug( - "Not all of the required keys present in payload. Missing: %s", - ", ".join(required_load_keys.difference(load)), - ) - return ret - if not fnd["path"]: - return ret - ret["dest"] = fnd["rel"] - gzip = load.get("gzip", None) - fpath = os.path.normpath(fnd["path"]) - with salt.utils.files.fopen(fpath, "rb") as fp_: - fp_.seek(load["loc"]) - data = fp_.read(__opts__["file_buffer_size"]) - if data and not salt.utils.files.is_binary(fpath): - data = data.decode(__salt_system_encoding__) - if gzip and data: - data = salt.utils.gzip_util.compress(data, gzip) - ret["gzip"] = gzip - ret["data"] = data - return ret - - -def update(): - """ - Update caches of the storage containers. - - Compares the md5 of the files on disk to the md5 of the blobs in the - container, and only updates if necessary. - - Also processes deletions by walking the container caches and comparing - with the list of blobs in the container - """ - for container in __opts__["azurefs"]: - path = _get_container_path(container) - try: - if not os.path.exists(path): - os.makedirs(path) - elif not os.path.isdir(path): - shutil.rmtree(path) - os.makedirs(path) - except Exception as exc: # pylint: disable=broad-except - log.exception("Error occurred creating cache directory for azurefs") - continue - blob_service = _get_container_service(container) - name = container["container_name"] - try: - blob_list = blob_service.list_blobs(name) - except Exception as exc: # pylint: disable=broad-except - log.exception("Error occurred fetching blob list for azurefs") - continue - - # Walk the cache directory searching for deletions - blob_names = [blob.name for blob in blob_list] - blob_set = set(blob_names) - for root, dirs, files in salt.utils.path.os_walk(path): - for f in files: - fname = os.path.join(root, f) - relpath = os.path.relpath(fname, path) - if relpath not in blob_set: - salt.fileserver.wait_lock(fname + ".lk", fname) - try: - os.unlink(fname) - except Exception: # pylint: disable=broad-except - pass - if not dirs and not files: - shutil.rmtree(root) - - for blob in blob_list: - fname = os.path.join(path, blob.name) - update = False - if os.path.exists(fname): - # File exists, check the hashes - source_md5 = blob.properties.content_settings.content_md5 - local_md5 = base64.b64encode( - salt.utils.hashutils.get_hash(fname, "md5").decode("hex") - ) - if local_md5 != source_md5: - update = True - else: - update = True - - if update: - if not os.path.exists(os.path.dirname(fname)): - os.makedirs(os.path.dirname(fname)) - # Lock writes - lk_fn = fname + ".lk" - salt.fileserver.wait_lock(lk_fn, fname) - with salt.utils.files.fopen(lk_fn, "w"): - pass - - try: - blob_service.get_blob_to_path(name, blob.name, fname) - except Exception as exc: # pylint: disable=broad-except - log.exception("Error occurred fetching blob from azurefs") - continue - - # Unlock writes - try: - os.unlink(lk_fn) - except Exception: # pylint: disable=broad-except - pass - - # Write out file list - container_list = path + ".list" - lk_fn = container_list + ".lk" - salt.fileserver.wait_lock(lk_fn, container_list) - with salt.utils.files.fopen(lk_fn, "w"): - pass - with salt.utils.files.fopen(container_list, "w") as fp_: - salt.utils.json.dump(blob_names, fp_) - try: - os.unlink(lk_fn) - except Exception: # pylint: disable=broad-except - pass - try: - hash_cachedir = os.path.join(__opts__["cachedir"], "azurefs", "hashes") - shutil.rmtree(hash_cachedir) - except Exception: # pylint: disable=broad-except - log.exception("Problem occurred trying to invalidate hash cach for azurefs") - - -def file_hash(load, fnd): - """ - Return a file hash based on the hash type set in the master config - """ - if not all(x in load for x in ("path", "saltenv")): - return "", None - ret = {"hash_type": __opts__["hash_type"]} - relpath = fnd["rel"] - path = fnd["path"] - hash_cachedir = os.path.join(__opts__["cachedir"], "azurefs", "hashes") - hashdest = salt.utils.path.join( - hash_cachedir, - load["saltenv"], - "{}.hash.{}".format(relpath, __opts__["hash_type"]), - ) - if not os.path.isfile(hashdest): - if not os.path.exists(os.path.dirname(hashdest)): - os.makedirs(os.path.dirname(hashdest)) - ret["hsum"] = salt.utils.hashutils.get_hash(path, __opts__["hash_type"]) - with salt.utils.files.fopen(hashdest, "w+") as fp_: - fp_.write(salt.utils.stringutils.to_str(ret["hsum"])) - return ret - else: - with salt.utils.files.fopen(hashdest, "rb") as fp_: - ret["hsum"] = salt.utils.stringutils.to_unicode(fp_.read()) - return ret - - -def file_list(load): - """ - Return a list of all files in a specified environment - """ - ret = set() - try: - for container in __opts__["azurefs"]: - if container.get("saltenv", "base") != load["saltenv"]: - continue - container_list = _get_container_path(container) + ".list" - lk = container_list + ".lk" - salt.fileserver.wait_lock(lk, container_list, 5) - if not os.path.exists(container_list): - continue - with salt.utils.files.fopen(container_list, "r") as fp_: - ret.update(set(salt.utils.json.load(fp_))) - except Exception as exc: # pylint: disable=broad-except - log.error( - "azurefs: an error ocurred retrieving file lists. " - "It should be resolved next time the fileserver " - "updates. Please do not manually modify the azurefs " - "cache directory." - ) - return list(ret) - - -def dir_list(load): - """ - Return a list of all directories in a specified environment - """ - ret = set() - files = file_list(load) - for f in files: - dirname = f - while dirname: - dirname = os.path.dirname(dirname) - if dirname: - ret.add(dirname) - return list(ret) - - -def _get_container_path(container): - """ - Get the cache path for the container in question - - Cache paths are generate by combining the account name, container name, - and saltenv, separated by underscores - """ - root = os.path.join(__opts__["cachedir"], "azurefs") - container_dir = "{}_{}_{}".format( - container.get("account_name", ""), - container.get("container_name", ""), - container.get("saltenv", "base"), - ) - return os.path.join(root, container_dir) - - -def _get_container_service(container): - """ - Get the azure block blob service for the container in question - - Try account_key, sas_token, and no auth in that order - """ - if "account_key" in container: - account = azure.storage.CloudStorageAccount( - container["account_name"], account_key=container["account_key"] - ) - elif "sas_token" in container: - account = azure.storage.CloudStorageAccount( - container["account_name"], sas_token=container["sas_token"] - ) - else: - account = azure.storage.CloudStorageAccount(container["account_name"]) - blob_service = account.create_block_blob_service() - return blob_service - - -def _validate_config(): - """ - Validate azurefs config, return False if it doesn't validate - """ - if not isinstance(__opts__["azurefs"], list): - log.error("azurefs configuration is not formed as a list, skipping azurefs") - return False - for container in __opts__["azurefs"]: - if not isinstance(container, dict): - log.error( - "One or more entries in the azurefs configuration list are " - "not formed as a dict. Skipping azurefs: %s", - container, - ) - return False - if "account_name" not in container or "container_name" not in container: - log.error( - "An azurefs container configuration is missing either an " - "account_name or a container_name: %s", - container, - ) - return False - return True diff --git a/salt/grains/metadata_azure.py b/salt/grains/metadata_azure.py deleted file mode 100644 index 4cdf8243473..00000000000 --- a/salt/grains/metadata_azure.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -Grains from cloud metadata servers at 169.254.169.254 in Azure Virtual Machine - -.. versionadded:: 3006.0 - -:depends: requests - -To enable these grains that pull from the http://169.254.169.254/metadata/instance?api-version=2020-09-01 -metadata server set `metadata_server_grains: True` in the minion config. - -.. code-block:: yaml - - metadata_server_grains: True - -""" - -import logging - -import salt.utils.http as http -import salt.utils.json - -HOST = "http://169.254.169.254" -URL = f"{HOST}/metadata/instance?api-version=2020-09-01" -log = logging.getLogger(__name__) - - -def __virtual__(): - # Check if metadata_server_grains minion option is enabled - if __opts__.get("metadata_server_grains", False) is False: - return False - azuretest = http.query( - URL, status=True, headers=True, header_list=["Metadata: true"] - ) - if azuretest.get("status", 404) != 200: - return False - return True - - -def metadata(): - """Takes no arguments, returns a dictionary of metadata values from Azure.""" - log.debug("All checks true - loading azure metadata") - result = http.query(URL, headers=True, header_list=["Metadata: true"]) - metadata = salt.utils.json.loads(result.get("body", {})) - - return metadata diff --git a/salt/modules/azurearm_compute.py b/salt/modules/azurearm_compute.py deleted file mode 100644 index 61ff7f85b2f..00000000000 --- a/salt/modules/azurearm_compute.py +++ /dev/null @@ -1,754 +0,0 @@ -""" -Azure (ARM) Compute Execution Module - -.. versionadded:: 2019.2.0 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -:maintainer: -:maturity: new -:depends: - * `azure `_ >= 2.0.0 - * `azure-common `_ >= 1.1.8 - * `azure-mgmt `_ >= 1.0.0 - * `azure-mgmt-compute `_ >= 1.0.0 - * `azure-mgmt-network `_ >= 1.7.1 - * `azure-mgmt-resource `_ >= 1.1.0 - * `azure-mgmt-storage `_ >= 1.0.0 - * `azure-mgmt-web `_ >= 0.32.0 - * `azure-storage `_ >= 0.34.3 - * `msrestazure `_ >= 0.4.21 -:platform: linux - -:configuration: This module requires Azure Resource Manager credentials to be passed as keyword arguments - to every function in order to work properly. - - Required provider parameters: - - if using username and password: - * ``subscription_id`` - * ``username`` - * ``password`` - - if using a service principal: - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - - Optional provider parameters: - -**cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. - Possible values: - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` - -""" - -# Python libs - -import logging -from functools import wraps - -import salt.utils.azurearm - -# Azure libs -HAS_LIBS = False -try: - import azure.mgmt.compute.models # pylint: disable=unused-import - from msrest.exceptions import SerializationError - from msrestazure.azure_exceptions import CloudError - - HAS_LIBS = True -except ImportError: - pass - -__virtualname__ = "azurearm_compute" - -log = logging.getLogger(__name__) - - -def __virtual__(): - if not HAS_LIBS: - return ( - False, - "The following dependencies are required to use the AzureARM modules: " - "Microsoft Azure SDK for Python >= 2.0rc6, " - "MS REST Azure (msrestazure) >= 0.4", - ) - - return __virtualname__ - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about azurearm deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "The 'azurearm' functionality in Salt has been deprecated and its " - "functionality will be removed in version 3007 in favor of the " - "saltext.azurerm Salt Extension. " - "(https://github.com/salt-extensions/saltext-azurerm)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -@_deprecation_message -def availability_set_create_or_update( - name, resource_group, **kwargs -): # pylint: disable=invalid-name - """ - .. versionadded:: 2019.2.0 - - Create or update an availability set. - - :param name: The availability set to create. - - :param resource_group: The resource group name assigned to the - availability set. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.availability_set_create_or_update testset testgroup - - """ - if "location" not in kwargs: - rg_props = __salt__["azurearm_resource.resource_group_get"]( - resource_group, **kwargs - ) - - if "error" in rg_props: - log.error("Unable to determine location from resource group specified.") - return False - kwargs["location"] = rg_props["location"] - - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - - # Use VM names to link to the IDs of existing VMs. - if isinstance(kwargs.get("virtual_machines"), list): - vm_list = [] - for vm_name in kwargs.get("virtual_machines"): - vm_instance = __salt__["azurearm_compute.virtual_machine_get"]( - name=vm_name, resource_group=resource_group, **kwargs - ) - if "error" not in vm_instance: - vm_list.append({"id": str(vm_instance["id"])}) - kwargs["virtual_machines"] = vm_list - - try: - setmodel = __utils__["azurearm.create_object_model"]( - "compute", "AvailabilitySet", **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - av_set = compconn.availability_sets.create_or_update( - resource_group_name=resource_group, - availability_set_name=name, - parameters=setmodel, - ) - result = av_set.as_dict() - - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def availability_set_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete an availability set. - - :param name: The availability set to delete. - - :param resource_group: The resource group name assigned to the - availability set. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.availability_set_delete testset testgroup - - """ - result = False - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - compconn.availability_sets.delete( - resource_group_name=resource_group, availability_set_name=name - ) - result = True - - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - - return result - - -@_deprecation_message -def availability_set_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get a dictionary representing an availability set's properties. - - :param name: The availability set to get. - - :param resource_group: The resource group name assigned to the - availability set. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.availability_set_get testset testgroup - - """ - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - av_set = compconn.availability_sets.get( - resource_group_name=resource_group, availability_set_name=name - ) - result = av_set.as_dict() - - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def availability_sets_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all availability sets within a resource group. - - :param resource_group: The resource group name to list availability - sets within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.availability_sets_list testgroup - - """ - result = {} - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - avail_sets = __utils__["azurearm.paged_object_to_list"]( - compconn.availability_sets.list(resource_group_name=resource_group) - ) - - for avail_set in avail_sets: - result[avail_set["name"]] = avail_set - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def availability_sets_list_available_sizes( - name, resource_group, **kwargs -): # pylint: disable=invalid-name - """ - .. versionadded:: 2019.2.0 - - List all available virtual machine sizes that can be used to - to create a new virtual machine in an existing availability set. - - :param name: The availability set name to list available - virtual machine sizes within. - - :param resource_group: The resource group name to list available - availability set sizes within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.availability_sets_list_available_sizes testset testgroup - - """ - result = {} - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - sizes = __utils__["azurearm.paged_object_to_list"]( - compconn.availability_sets.list_available_sizes( - resource_group_name=resource_group, availability_set_name=name - ) - ) - - for size in sizes: - result[size["name"]] = size - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machine_capture( - name, destination_name, resource_group, prefix="capture-", overwrite=False, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Captures the VM by copying virtual hard disks of the VM and outputs - a template that can be used to create similar VMs. - - :param name: The name of the virtual machine. - - :param destination_name: The destination container name. - - :param resource_group: The resource group name assigned to the - virtual machine. - - :param prefix: (Default: 'capture-') The captured virtual hard disk's name prefix. - - :param overwrite: (Default: False) Overwrite the destination disk in case of conflict. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machine_capture testvm testcontainer testgroup - - """ - # pylint: disable=invalid-name - VirtualMachineCaptureParameters = getattr( - azure.mgmt.compute.models, "VirtualMachineCaptureParameters" - ) - - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - # pylint: disable=invalid-name - vm = compconn.virtual_machines.capture( - resource_group_name=resource_group, - vm_name=name, - parameters=VirtualMachineCaptureParameters( - vhd_prefix=prefix, - destination_container_name=destination_name, - overwrite_vhds=overwrite, - ), - ) - vm.wait() - vm_result = vm.result() - result = vm_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machine_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Retrieves information about the model view or the instance view of a - virtual machine. - - :param name: The name of the virtual machine. - - :param resource_group: The resource group name assigned to the - virtual machine. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machine_get testvm testgroup - - """ - expand = kwargs.get("expand") - - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - # pylint: disable=invalid-name - vm = compconn.virtual_machines.get( - resource_group_name=resource_group, vm_name=name, expand=expand - ) - result = vm.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machine_convert_to_managed_disks( - name, resource_group, **kwargs -): # pylint: disable=invalid-name - """ - .. versionadded:: 2019.2.0 - - Converts virtual machine disks from blob-based to managed disks. Virtual - machine must be stop-deallocated before invoking this operation. - - :param name: The name of the virtual machine to convert. - - :param resource_group: The resource group name assigned to the - virtual machine. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machine_convert_to_managed_disks testvm testgroup - - """ - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - # pylint: disable=invalid-name - vm = compconn.virtual_machines.convert_to_managed_disks( - resource_group_name=resource_group, vm_name=name - ) - vm.wait() - vm_result = vm.result() - result = vm_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machine_deallocate(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Power off a virtual machine and deallocate compute resources. - - :param name: The name of the virtual machine to deallocate. - - :param resource_group: The resource group name assigned to the - virtual machine. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machine_deallocate testvm testgroup - - """ - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - # pylint: disable=invalid-name - vm = compconn.virtual_machines.deallocate( - resource_group_name=resource_group, vm_name=name - ) - vm.wait() - vm_result = vm.result() - result = vm_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machine_generalize(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Set the state of a virtual machine to 'generalized'. - - :param name: The name of the virtual machine. - - :param resource_group: The resource group name assigned to the - virtual machine. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machine_generalize testvm testgroup - - """ - result = False - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - compconn.virtual_machines.generalize( - resource_group_name=resource_group, vm_name=name - ) - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - - return result - - -@_deprecation_message -def virtual_machines_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all virtual machines within a resource group. - - :param resource_group: The resource group name to list virtual - machines within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machines_list testgroup - - """ - result = {} - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - vms = __utils__["azurearm.paged_object_to_list"]( - compconn.virtual_machines.list(resource_group_name=resource_group) - ) - for vm in vms: # pylint: disable=invalid-name - result[vm["name"]] = vm - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machines_list_all(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all virtual machines within a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machines_list_all - - """ - result = {} - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - vms = __utils__["azurearm.paged_object_to_list"]( - compconn.virtual_machines.list_all() - ) - for vm in vms: # pylint: disable=invalid-name - result[vm["name"]] = vm - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machines_list_available_sizes( - name, resource_group, **kwargs -): # pylint: disable=invalid-name - """ - .. versionadded:: 2019.2.0 - - Lists all available virtual machine sizes to which the specified virtual - machine can be resized. - - :param name: The name of the virtual machine. - - :param resource_group: The resource group name assigned to the - virtual machine. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machines_list_available_sizes testvm testgroup - - """ - result = {} - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - sizes = __utils__["azurearm.paged_object_to_list"]( - compconn.virtual_machines.list_available_sizes( - resource_group_name=resource_group, vm_name=name - ) - ) - for size in sizes: - result[size["name"]] = size - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machine_power_off(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Power off (stop) a virtual machine. - - :param name: The name of the virtual machine to stop. - - :param resource_group: The resource group name assigned to the - virtual machine. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machine_power_off testvm testgroup - - """ - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - # pylint: disable=invalid-name - vm = compconn.virtual_machines.power_off( - resource_group_name=resource_group, vm_name=name - ) - vm.wait() - vm_result = vm.result() - result = vm_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machine_restart(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Restart a virtual machine. - - :param name: The name of the virtual machine to restart. - - :param resource_group: The resource group name assigned to the - virtual machine. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machine_restart testvm testgroup - - """ - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - # pylint: disable=invalid-name - vm = compconn.virtual_machines.restart( - resource_group_name=resource_group, vm_name=name - ) - vm.wait() - vm_result = vm.result() - result = vm_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machine_start(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Power on (start) a virtual machine. - - :param name: The name of the virtual machine to start. - - :param resource_group: The resource group name assigned to the - virtual machine. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machine_start testvm testgroup - - """ - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - # pylint: disable=invalid-name - vm = compconn.virtual_machines.start( - resource_group_name=resource_group, vm_name=name - ) - vm.wait() - vm_result = vm.result() - result = vm_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_machine_redeploy(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Redeploy a virtual machine. - - :param name: The name of the virtual machine to redeploy. - - :param resource_group: The resource group name assigned to the - virtual machine. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_compute.virtual_machine_redeploy testvm testgroup - - """ - compconn = __utils__["azurearm.get_client"]("compute", **kwargs) - try: - # pylint: disable=invalid-name - vm = compconn.virtual_machines.redeploy( - resource_group_name=resource_group, vm_name=name - ) - vm.wait() - vm_result = vm.result() - result = vm_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("compute", str(exc), **kwargs) - result = {"error": str(exc)} - - return result diff --git a/salt/modules/azurearm_dns.py b/salt/modules/azurearm_dns.py deleted file mode 100644 index e503712f264..00000000000 --- a/salt/modules/azurearm_dns.py +++ /dev/null @@ -1,552 +0,0 @@ -""" -Azure (ARM) DNS Execution Module - -.. versionadded:: 3000 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -:maintainer: -:maturity: new -:depends: - * `azure `_ >= 2.0.0 - * `azure-common `_ >= 1.1.8 - * `azure-mgmt `_ >= 1.0.0 - * `azure-mgmt-compute `_ >= 1.0.0 - * `azure-mgmt-dns `_ >= 2.0.0rc1 - * `azure-mgmt-network `_ >= 1.7.1 - * `azure-mgmt-resource `_ >= 1.1.0 - * `azure-mgmt-storage `_ >= 1.0.0 - * `azure-mgmt-web `_ >= 0.32.0 - * `azure-storage `_ >= 0.34.3 - * `msrestazure `_ >= 0.4.21 - -:platform: linux -:configuration: - This module requires Azure Resource Manager credentials to be passed as keyword arguments - to every function in order to work properly. - -Required provider parameters: - - if using username and password: - - * ``subscription_id`` - * ``username`` - * ``password`` - - if using a service principal: - - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - -Optional provider parameters: - - **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. - - Possible values: - - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` - -""" - -# Python libs - -import logging -from functools import wraps - -import salt.utils.azurearm - -# Azure libs -HAS_LIBS = False -try: - import azure.mgmt.dns.models # pylint: disable=unused-import - from msrest.exceptions import SerializationError - from msrestazure.azure_exceptions import CloudError - - HAS_LIBS = True -except ImportError: - pass - -__virtualname__ = "azurearm_dns" - -log = logging.getLogger(__name__) - - -def __virtual__(): - if not HAS_LIBS: - return ( - False, - "The following dependencies are required to use the AzureARM modules: " - "Microsoft Azure SDK for Python >= 2.0rc6, " - "MS REST Azure (msrestazure) >= 0.4", - ) - - return __virtualname__ - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about azurearm deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "The 'azurearm' functionality in Salt has been deprecated and its " - "functionality will be removed in version 3007 in favor of the " - "saltext.azurerm Salt Extension. " - "(https://github.com/salt-extensions/saltext-azurerm)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -@_deprecation_message -def record_set_create_or_update(name, zone_name, resource_group, record_type, **kwargs): - """ - .. versionadded:: 3000 - - Creates or updates a record set within a DNS zone. - - :param name: The name of the record set, relative to the name of the zone. - - :param zone_name: The name of the DNS zone (without a terminating dot). - - :param resource_group: The name of the resource group. - - :param record_type: - The type of DNS record in this record set. Record sets of type SOA can be - updated but not created (they are created when the DNS zone is created). - Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.record_set_create_or_update myhost myzone testgroup A - arecords='[{ipv4_address: 10.0.0.1}]' ttl=300 - - """ - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - - try: - record_set_model = __utils__["azurearm.create_object_model"]( - "dns", "RecordSet", **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - record_set = dnsconn.record_sets.create_or_update( - relative_record_set_name=name, - zone_name=zone_name, - resource_group_name=resource_group, - record_type=record_type, - parameters=record_set_model, - if_match=kwargs.get("if_match"), - if_none_match=kwargs.get("if_none_match"), - ) - result = record_set.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def record_set_delete(name, zone_name, resource_group, record_type, **kwargs): - """ - .. versionadded:: 3000 - - Deletes a record set from a DNS zone. This operation cannot be undone. - - :param name: The name of the record set, relative to the name of the zone. - - :param zone_name: The name of the DNS zone (without a terminating dot). - - :param resource_group: The name of the resource group. - - :param record_type: - The type of DNS record in this record set. Record sets of type SOA cannot be - deleted (they are deleted when the DNS zone is deleted). - Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.record_set_delete myhost myzone testgroup A - - """ - result = False - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - try: - record_set = dnsconn.record_sets.delete( - relative_record_set_name=name, - zone_name=zone_name, - resource_group_name=resource_group, - record_type=record_type, - if_match=kwargs.get("if_match"), - ) - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - - return result - - -@_deprecation_message -def record_set_get(name, zone_name, resource_group, record_type, **kwargs): - """ - .. versionadded:: 3000 - - Get a dictionary representing a record set's properties. - - :param name: The name of the record set, relative to the name of the zone. - - :param zone_name: The name of the DNS zone (without a terminating dot). - - :param resource_group: The name of the resource group. - - :param record_type: - The type of DNS record in this record set. - Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.record_set_get '@' myzone testgroup SOA - - """ - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - try: - record_set = dnsconn.record_sets.get( - relative_record_set_name=name, - zone_name=zone_name, - resource_group_name=resource_group, - record_type=record_type, - ) - result = record_set.as_dict() - - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def record_sets_list_by_type( - zone_name, resource_group, record_type, top=None, recordsetnamesuffix=None, **kwargs -): - """ - .. versionadded:: 3000 - - Lists the record sets of a specified type in a DNS zone. - - :param zone_name: The name of the DNS zone (without a terminating dot). - - :param resource_group: The name of the resource group. - - :param record_type: - The type of record sets to enumerate. - Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' - - :param top: - The maximum number of record sets to return. If not specified, - returns up to 100 record sets. - - :param recordsetnamesuffix: - The suffix label of the record set name that has - to be used to filter the record set enumerations. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.record_sets_list_by_type myzone testgroup SOA - - """ - result = {} - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - try: - record_sets = __utils__["azurearm.paged_object_to_list"]( - dnsconn.record_sets.list_by_type( - zone_name=zone_name, - resource_group_name=resource_group, - record_type=record_type, - top=top, - recordsetnamesuffix=recordsetnamesuffix, - ) - ) - - for record_set in record_sets: - result[record_set["name"]] = record_set - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def record_sets_list_by_dns_zone( - zone_name, resource_group, top=None, recordsetnamesuffix=None, **kwargs -): - """ - .. versionadded:: 3000 - - Lists all record sets in a DNS zone. - - :param zone_name: The name of the DNS zone (without a terminating dot). - - :param resource_group: The name of the resource group. - - :param top: - The maximum number of record sets to return. If not specified, - returns up to 100 record sets. - - :param recordsetnamesuffix: - The suffix label of the record set name that has - to be used to filter the record set enumerations. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.record_sets_list_by_dns_zone myzone testgroup - - """ - result = {} - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - try: - record_sets = __utils__["azurearm.paged_object_to_list"]( - dnsconn.record_sets.list_by_dns_zone( - zone_name=zone_name, - resource_group_name=resource_group, - top=top, - recordsetnamesuffix=recordsetnamesuffix, - ) - ) - - for record_set in record_sets: - result[record_set["name"]] = record_set - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def zone_create_or_update(name, resource_group, **kwargs): - """ - .. versionadded:: 3000 - - Creates or updates a DNS zone. Does not modify DNS records within the zone. - - :param name: The name of the DNS zone to create (without a terminating dot). - - :param resource_group: The name of the resource group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.zone_create_or_update myzone testgroup - - """ - # DNS zones are global objects - kwargs["location"] = "global" - - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - - # Convert list of ID strings to list of dictionaries with id key. - if isinstance(kwargs.get("registration_virtual_networks"), list): - kwargs["registration_virtual_networks"] = [ - {"id": vnet} for vnet in kwargs["registration_virtual_networks"] - ] - - if isinstance(kwargs.get("resolution_virtual_networks"), list): - kwargs["resolution_virtual_networks"] = [ - {"id": vnet} for vnet in kwargs["resolution_virtual_networks"] - ] - - try: - zone_model = __utils__["azurearm.create_object_model"]("dns", "Zone", **kwargs) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - zone = dnsconn.zones.create_or_update( - zone_name=name, - resource_group_name=resource_group, - parameters=zone_model, - if_match=kwargs.get("if_match"), - if_none_match=kwargs.get("if_none_match"), - ) - result = zone.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def zone_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 3000 - - Delete a DNS zone within a resource group. - - :param name: The name of the DNS zone to delete. - - :param resource_group: The name of the resource group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.zone_delete myzone testgroup - - """ - result = False - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - try: - zone = dnsconn.zones.delete( - zone_name=name, - resource_group_name=resource_group, - if_match=kwargs.get("if_match"), - ) - zone.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - - return result - - -@_deprecation_message -def zone_get(name, resource_group, **kwargs): - """ - .. versionadded:: 3000 - - Get a dictionary representing a DNS zone's properties, but not the - record sets within the zone. - - :param name: The DNS zone to get. - - :param resource_group: The name of the resource group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.zone_get myzone testgroup - - """ - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - try: - zone = dnsconn.zones.get(zone_name=name, resource_group_name=resource_group) - result = zone.as_dict() - - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def zones_list_by_resource_group(resource_group, top=None, **kwargs): - """ - .. versionadded:: 3000 - - Lists the DNS zones in a resource group. - - :param resource_group: The name of the resource group. - - :param top: - The maximum number of DNS zones to return. If not specified, - returns up to 100 zones. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.zones_list_by_resource_group testgroup - - """ - result = {} - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - try: - zones = __utils__["azurearm.paged_object_to_list"]( - dnsconn.zones.list_by_resource_group( - resource_group_name=resource_group, top=top - ) - ) - - for zone in zones: - result[zone["name"]] = zone - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def zones_list(top=None, **kwargs): - """ - .. versionadded:: 3000 - - Lists the DNS zones in all resource groups in a subscription. - - :param top: - The maximum number of DNS zones to return. If not specified, - eturns up to 100 zones. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_dns.zones_list - - """ - result = {} - dnsconn = __utils__["azurearm.get_client"]("dns", **kwargs) - try: - zones = __utils__["azurearm.paged_object_to_list"](dnsconn.zones.list(top=top)) - - for zone in zones: - result[zone["name"]] = zone - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("dns", str(exc), **kwargs) - result = {"error": str(exc)} - - return result diff --git a/salt/modules/azurearm_network.py b/salt/modules/azurearm_network.py deleted file mode 100644 index c8e520c3cf2..00000000000 --- a/salt/modules/azurearm_network.py +++ /dev/null @@ -1,2859 +0,0 @@ -""" -Azure (ARM) Network Execution Module - -.. versionadded:: 2019.2.0 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -:maintainer: -:maturity: new -:depends: - * `azure `_ >= 2.0.0 - * `azure-common `_ >= 1.1.8 - * `azure-mgmt `_ >= 1.0.0 - * `azure-mgmt-compute `_ >= 1.0.0 - * `azure-mgmt-network `_ >= 1.7.1 - * `azure-mgmt-resource `_ >= 1.1.0 - * `azure-mgmt-storage `_ >= 1.0.0 - * `azure-mgmt-web `_ >= 0.32.0 - * `azure-storage `_ >= 0.34.3 - * `msrestazure `_ >= 0.4.21 -:platform: linux - -:configuration: This module requires Azure Resource Manager credentials to be passed as keyword arguments - to every function in order to work properly. - - Required provider parameters: - - if using username and password: - * ``subscription_id`` - * ``username`` - * ``password`` - - if using a service principal: - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - - Optional provider parameters: - -**cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. - Possible values: - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` - -""" - -# Python libs - -import logging -from functools import wraps - -# Salt libs -import salt.utils.azurearm -from salt.exceptions import SaltInvocationError # pylint: disable=unused-import - -# Azure libs -HAS_LIBS = False -try: - import azure.mgmt.network.models # pylint: disable=unused-import - from msrest.exceptions import SerializationError - from msrestazure.azure_exceptions import CloudError - - HAS_LIBS = True -except ImportError: - pass - -__virtualname__ = "azurearm_network" - -log = logging.getLogger(__name__) - - -def __virtual__(): - if not HAS_LIBS: - return ( - False, - "The following dependencies are required to use the AzureARM modules: " - "Microsoft Azure SDK for Python >= 2.0rc6, " - "MS REST Azure (msrestazure) >= 0.4", - ) - - return __virtualname__ - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about azurearm deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "The 'azurearm' functionality in Salt has been deprecated and its " - "functionality will be removed in version 3007 in favor of the " - "saltext.azurerm Salt Extension. " - "(https://github.com/salt-extensions/saltext-azurerm)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -@_deprecation_message -def check_dns_name_availability(name, region, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Check whether a domain name in the current zone is available for use. - - :param name: The DNS name to query. - - :param region: The region to query for the DNS name in question. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.check_dns_name_availability testdnsname westus - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - check_dns_name = netconn.check_dns_name_availability( - location=region, domain_name_label=name - ) - result = check_dns_name.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def check_ip_address_availability( - ip_address, virtual_network, resource_group, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Check that a private ip address is available within the specified - virtual network. - - :param ip_address: The ip_address to query. - - :param virtual_network: The virtual network to query for the IP address - in question. - - :param resource_group: The resource group name assigned to the - virtual network. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.check_ip_address_availability 10.0.0.4 testnet testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - check_ip = netconn.virtual_networks.check_ip_address_availability( - resource_group_name=resource_group, - virtual_network_name=virtual_network, - ip_address=ip_address, - ) - result = check_ip.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def default_security_rule_get(name, security_group, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a default security rule within a security group. - - :param name: The name of the security rule to query. - - :param security_group: The network security group containing the - security rule. - - :param resource_group: The resource group name assigned to the - network security group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.default_security_rule_get DenyAllOutBound testnsg testgroup - - """ - result = {} - - default_rules = default_security_rules_list( - security_group=security_group, resource_group=resource_group, **kwargs - ) - - if isinstance(default_rules, dict) and "error" in default_rules: - return default_rules - - try: - for default_rule in default_rules: - if default_rule["name"] == name: - result = default_rule - if not result: - result = {"error": "Unable to find {} in {}!".format(name, security_group)} - except KeyError as exc: - log.error("Unable to find %s in %s!", name, security_group) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def default_security_rules_list(security_group, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List default security rules within a security group. - - :param security_group: The network security group to query. - - :param resource_group: The resource group name assigned to the - network security group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.default_security_rules_list testnsg testgroup - - """ - result = {} - - secgroup = network_security_group_get( - security_group=security_group, resource_group=resource_group, **kwargs - ) - - if "error" in secgroup: - return secgroup - - try: - result = secgroup["default_security_rules"] - except KeyError as exc: - log.error("No default security rules found for %s!", security_group) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def security_rules_list(security_group, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List security rules within a network security group. - - :param security_group: The network security group to query. - - :param resource_group: The resource group name assigned to the - network security group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.security_rules_list testnsg testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - secrules = netconn.security_rules.list( - network_security_group_name=security_group, - resource_group_name=resource_group, - ) - result = __utils__["azurearm.paged_object_to_list"](secrules) - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def security_rule_create_or_update( - name, - access, - direction, - priority, - protocol, - security_group, - resource_group, - source_address_prefix=None, - destination_address_prefix=None, - source_port_range=None, - destination_port_range=None, - source_address_prefixes=None, - destination_address_prefixes=None, - source_port_ranges=None, - destination_port_ranges=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Create or update a security rule within a specified network security group. - - :param name: The name of the security rule to create. - - :param access: - 'allow' or 'deny' - - :param direction: - 'inbound' or 'outbound' - - :param priority: - Integer between 100 and 4096 used for ordering rule application. - - :param protocol: - 'tcp', 'udp', or '*' - - :param destination_address_prefix: - The CIDR or destination IP range. Asterix '*' can also be used to match all destination IPs. - Default tags such as 'VirtualNetwork', 'AzureLoadBalancer' and 'Internet' can also be used. - If this is an ingress rule, specifies where network traffic originates from. - - :param destination_port_range: - The destination port or range. Integer or range between 0 and 65535. Asterix '*' - can also be used to match all ports. - - :param source_address_prefix: - The CIDR or source IP range. Asterix '*' can also be used to match all source IPs. - Default tags such as 'VirtualNetwork', 'AzureLoadBalancer' and 'Internet' can also be used. - If this is an ingress rule, specifies where network traffic originates from. - - :param source_port_range: - The source port or range. Integer or range between 0 and 65535. Asterix '*' - can also be used to match all ports. - - :param destination_address_prefixes: - A list of destination_address_prefix values. This parameter overrides destination_address_prefix - and will cause any value entered there to be ignored. - - :param destination_port_ranges: - A list of destination_port_range values. This parameter overrides destination_port_range - and will cause any value entered there to be ignored. - - :param source_address_prefixes: - A list of source_address_prefix values. This parameter overrides source_address_prefix - and will cause any value entered there to be ignored. - - :param source_port_ranges: - A list of source_port_range values. This parameter overrides source_port_range - and will cause any value entered there to be ignored. - - :param security_group: The network security group containing the - security rule. - - :param resource_group: The resource group name assigned to the - network security group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.security_rule_create_or_update testrule1 allow outbound 101 tcp testnsg testgroup \ - source_address_prefix='*' destination_address_prefix=internet source_port_range='*' \ - destination_port_range='1-1024' - - """ - exclusive_params = [ - ("source_port_ranges", "source_port_range"), - ("source_address_prefixes", "source_address_prefix"), - ("destination_port_ranges", "destination_port_range"), - ("destination_address_prefixes", "destination_address_prefix"), - ] - - for params in exclusive_params: - # pylint: disable=eval-used - if not eval(params[0]) and not eval(params[1]): - log.error( - "Either the %s or %s parameter must be provided!", params[0], params[1] - ) - return False - # pylint: disable=eval-used - if eval(params[0]): - # pylint: disable=exec-used - exec("{} = None".format(params[1])) - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - rulemodel = __utils__["azurearm.create_object_model"]( - "network", - "SecurityRule", - name=name, - access=access, - direction=direction, - priority=priority, - protocol=protocol, - source_port_ranges=source_port_ranges, - source_port_range=source_port_range, - source_address_prefixes=source_address_prefixes, - source_address_prefix=source_address_prefix, - destination_port_ranges=destination_port_ranges, - destination_port_range=destination_port_range, - destination_address_prefixes=destination_address_prefixes, - destination_address_prefix=destination_address_prefix, - **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - secrule = netconn.security_rules.create_or_update( - resource_group_name=resource_group, - network_security_group_name=security_group, - security_rule_name=name, - security_rule_parameters=rulemodel, - ) - secrule.wait() - secrule_result = secrule.result() - result = secrule_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def security_rule_delete(security_rule, security_group, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a security rule within a specified security group. - - :param name: The name of the security rule to delete. - - :param security_group: The network security group containing the - security rule. - - :param resource_group: The resource group name assigned to the - network security group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.security_rule_delete testrule1 testnsg testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - secrule = netconn.security_rules.delete( - network_security_group_name=security_group, - resource_group_name=resource_group, - security_rule_name=security_rule, - ) - secrule.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def security_rule_get(security_rule, security_group, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get a security rule within a specified network security group. - - :param name: The name of the security rule to query. - - :param security_group: The network security group containing the - security rule. - - :param resource_group: The resource group name assigned to the - network security group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.security_rule_get testrule1 testnsg testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - secrule = netconn.security_rules.get( - network_security_group_name=security_group, - resource_group_name=resource_group, - security_rule_name=security_rule, - ) - result = secrule.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def network_security_group_create_or_update( - name, resource_group, **kwargs -): # pylint: disable=invalid-name - """ - .. versionadded:: 2019.2.0 - - Create or update a network security group. - - :param name: The name of the network security group to create. - - :param resource_group: The resource group name assigned to the - network security group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_security_group_create_or_update testnsg testgroup - - """ - if "location" not in kwargs: - rg_props = __salt__["azurearm_resource.resource_group_get"]( - resource_group, **kwargs - ) - - if "error" in rg_props: - log.error("Unable to determine location from resource group specified.") - return False - kwargs["location"] = rg_props["location"] - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - secgroupmodel = __utils__["azurearm.create_object_model"]( - "network", "NetworkSecurityGroup", **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - secgroup = netconn.network_security_groups.create_or_update( - resource_group_name=resource_group, - network_security_group_name=name, - parameters=secgroupmodel, - ) - secgroup.wait() - secgroup_result = secgroup.result() - result = secgroup_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def network_security_group_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a network security group within a resource group. - - :param name: The name of the network security group to delete. - - :param resource_group: The resource group name assigned to the - network security group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_security_group_delete testnsg testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - secgroup = netconn.network_security_groups.delete( - resource_group_name=resource_group, network_security_group_name=name - ) - secgroup.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def network_security_group_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a network security group within a resource group. - - :param name: The name of the network security group to query. - - :param resource_group: The resource group name assigned to the - network security group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_security_group_get testnsg testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - secgroup = netconn.network_security_groups.get( - resource_group_name=resource_group, network_security_group_name=name - ) - result = secgroup.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def network_security_groups_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all network security groups within a resource group. - - :param resource_group: The resource group name to list network security \ - groups within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_security_groups_list testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - secgroups = __utils__["azurearm.paged_object_to_list"]( - netconn.network_security_groups.list(resource_group_name=resource_group) - ) - for secgroup in secgroups: - result[secgroup["name"]] = secgroup - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def network_security_groups_list_all(**kwargs): # pylint: disable=invalid-name - """ - .. versionadded:: 2019.2.0 - - List all network security groups within a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_security_groups_list_all - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - secgroups = __utils__["azurearm.paged_object_to_list"]( - netconn.network_security_groups.list_all() - ) - for secgroup in secgroups: - result[secgroup["name"]] = secgroup - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def subnets_list(virtual_network, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all subnets within a virtual network. - - :param virtual_network: The virtual network name to list subnets within. - - :param resource_group: The resource group name assigned to the - virtual network. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.subnets_list testnet testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - subnets = __utils__["azurearm.paged_object_to_list"]( - netconn.subnets.list( - resource_group_name=resource_group, virtual_network_name=virtual_network - ) - ) - - for subnet in subnets: - result[subnet["name"]] = subnet - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def subnet_get(name, virtual_network, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific subnet. - - :param name: The name of the subnet to query. - - :param virtual_network: The virtual network name containing the - subnet. - - :param resource_group: The resource group name assigned to the - virtual network. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.subnet_get testsubnet testnet testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - subnet = netconn.subnets.get( - resource_group_name=resource_group, - virtual_network_name=virtual_network, - subnet_name=name, - ) - - result = subnet.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def subnet_create_or_update( - name, address_prefix, virtual_network, resource_group, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Create or update a subnet. - - :param name: The name assigned to the subnet being created or updated. - - :param address_prefix: A valid CIDR block within the virtual network. - - :param virtual_network: The virtual network name containing the - subnet. - - :param resource_group: The resource group name assigned to the - virtual network. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.subnet_create_or_update testsubnet \ - '10.0.0.0/24' testnet testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - # Use NSG name to link to the ID of an existing NSG. - if kwargs.get("network_security_group"): - nsg = network_security_group_get( - name=kwargs["network_security_group"], - resource_group=resource_group, - **kwargs - ) - if "error" not in nsg: - kwargs["network_security_group"] = {"id": str(nsg["id"])} - - # Use Route Table name to link to the ID of an existing Route Table. - if kwargs.get("route_table"): - rt_table = route_table_get( - name=kwargs["route_table"], resource_group=resource_group, **kwargs - ) - if "error" not in rt_table: - kwargs["route_table"] = {"id": str(rt_table["id"])} - - try: - snetmodel = __utils__["azurearm.create_object_model"]( - "network", - "Subnet", - address_prefix=address_prefix, - resource_group=resource_group, - **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - subnet = netconn.subnets.create_or_update( - resource_group_name=resource_group, - virtual_network_name=virtual_network, - subnet_name=name, - subnet_parameters=snetmodel, - ) - subnet.wait() - sn_result = subnet.result() - result = sn_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def subnet_delete(name, virtual_network, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a subnet. - - :param name: The name of the subnet to delete. - - :param virtual_network: The virtual network name containing the - subnet. - - :param resource_group: The resource group name assigned to the - virtual network. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.subnet_delete testsubnet testnet testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - subnet = netconn.subnets.delete( - resource_group_name=resource_group, - virtual_network_name=virtual_network, - subnet_name=name, - ) - subnet.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def virtual_networks_list_all(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all virtual networks within a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.virtual_networks_list_all - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - vnets = __utils__["azurearm.paged_object_to_list"]( - netconn.virtual_networks.list_all() - ) - - for vnet in vnets: - result[vnet["name"]] = vnet - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def virtual_networks_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all virtual networks within a resource group. - - :param resource_group: The resource group name to list virtual networks - within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.virtual_networks_list testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - vnets = __utils__["azurearm.paged_object_to_list"]( - netconn.virtual_networks.list(resource_group_name=resource_group) - ) - - for vnet in vnets: - result[vnet["name"]] = vnet - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -# pylint: disable=invalid-name -@_deprecation_message -def virtual_network_create_or_update(name, address_prefixes, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Create or update a virtual network. - - :param name: The name assigned to the virtual network being - created or updated. - - :param address_prefixes: A list of CIDR blocks which can be used - by subnets within the virtual network. - - :param resource_group: The resource group name assigned to the - virtual network. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.virtual_network_create_or_update \ - testnet ['10.0.0.0/16'] testgroup - - """ - if "location" not in kwargs: - rg_props = __salt__["azurearm_resource.resource_group_get"]( - resource_group, **kwargs - ) - - if "error" in rg_props: - log.error("Unable to determine location from resource group specified.") - return False - kwargs["location"] = rg_props["location"] - - if not isinstance(address_prefixes, list): - log.error("Address prefixes must be specified as a list!") - return False - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - address_space = {"address_prefixes": address_prefixes} - dhcp_options = {"dns_servers": kwargs.get("dns_servers")} - - try: - vnetmodel = __utils__["azurearm.create_object_model"]( - "network", - "VirtualNetwork", - address_space=address_space, - dhcp_options=dhcp_options, - **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - vnet = netconn.virtual_networks.create_or_update( - virtual_network_name=name, - resource_group_name=resource_group, - parameters=vnetmodel, - ) - vnet.wait() - vnet_result = vnet.result() - result = vnet_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def virtual_network_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a virtual network. - - :param name: The name of the virtual network to delete. - - :param resource_group: The resource group name assigned to the - virtual network - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.virtual_network_delete testnet testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - vnet = netconn.virtual_networks.delete( - virtual_network_name=name, resource_group_name=resource_group - ) - vnet.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def virtual_network_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific virtual network. - - :param name: The name of the virtual network to query. - - :param resource_group: The resource group name assigned to the - virtual network. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.virtual_network_get testnet testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - vnet = netconn.virtual_networks.get( - virtual_network_name=name, resource_group_name=resource_group - ) - result = vnet.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def load_balancers_list_all(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all load balancers within a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.load_balancers_list_all - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - load_balancers = __utils__["azurearm.paged_object_to_list"]( - netconn.load_balancers.list_all() - ) - - for load_balancer in load_balancers: - result[load_balancer["name"]] = load_balancer - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def load_balancers_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all load balancers within a resource group. - - :param resource_group: The resource group name to list load balancers - within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.load_balancers_list testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - load_balancers = __utils__["azurearm.paged_object_to_list"]( - netconn.load_balancers.list(resource_group_name=resource_group) - ) - - for load_balancer in load_balancers: - result[load_balancer["name"]] = load_balancer - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def load_balancer_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific load balancer. - - :param name: The name of the load balancer to query. - - :param resource_group: The resource group name assigned to the - load balancer. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.load_balancer_get testlb testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - load_balancer = netconn.load_balancers.get( - load_balancer_name=name, resource_group_name=resource_group - ) - result = load_balancer.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def load_balancer_create_or_update(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Create or update a load balancer within a specified resource group. - - :param name: The name of the load balancer to create. - - :param resource_group: The resource group name assigned to the - load balancer. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.load_balancer_create_or_update testlb testgroup - - """ - if "location" not in kwargs: - rg_props = __salt__["azurearm_resource.resource_group_get"]( - resource_group, **kwargs - ) - - if "error" in rg_props: - log.error("Unable to determine location from resource group specified.") - return False - kwargs["location"] = rg_props["location"] - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - if isinstance(kwargs.get("frontend_ip_configurations"), list): - for idx in range(0, len(kwargs["frontend_ip_configurations"])): - # Use Public IP Address name to link to the ID of an existing Public IP - if "public_ip_address" in kwargs["frontend_ip_configurations"][idx]: - pub_ip = public_ip_address_get( - name=kwargs["frontend_ip_configurations"][idx]["public_ip_address"], - resource_group=resource_group, - **kwargs - ) - if "error" not in pub_ip: - kwargs["frontend_ip_configurations"][idx]["public_ip_address"] = { - "id": str(pub_ip["id"]) - } - # Use Subnet name to link to the ID of an existing Subnet - elif "subnet" in kwargs["frontend_ip_configurations"][idx]: - vnets = virtual_networks_list(resource_group=resource_group, **kwargs) - if "error" not in vnets: - for vnet in vnets: - subnets = subnets_list( - virtual_network=vnet, - resource_group=resource_group, - **kwargs - ) - if ( - kwargs["frontend_ip_configurations"][idx]["subnet"] - in subnets - ): - kwargs["frontend_ip_configurations"][idx]["subnet"] = { - "id": str( - subnets[ - kwargs["frontend_ip_configurations"][idx][ - "subnet" - ] - ]["id"] - ) - } - break - - id_url = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Network/loadBalancers/{2}/{3}/{4}" - - if isinstance(kwargs.get("load_balancing_rules"), list): - for idx in range(0, len(kwargs["load_balancing_rules"])): - # Link to sub-objects which might be created at the same time as the load balancer - if "frontend_ip_configuration" in kwargs["load_balancing_rules"][idx]: - kwargs["load_balancing_rules"][idx]["frontend_ip_configuration"] = { - "id": id_url.format( - kwargs.get("subscription_id"), - resource_group, - name, - "frontendIPConfigurations", - kwargs["load_balancing_rules"][idx][ - "frontend_ip_configuration" - ], - ) - } - if "backend_address_pool" in kwargs["load_balancing_rules"][idx]: - kwargs["load_balancing_rules"][idx]["backend_address_pool"] = { - "id": id_url.format( - kwargs.get("subscription_id"), - resource_group, - name, - "backendAddressPools", - kwargs["load_balancing_rules"][idx]["backend_address_pool"], - ) - } - if "probe" in kwargs["load_balancing_rules"][idx]: - kwargs["load_balancing_rules"][idx]["probe"] = { - "id": id_url.format( - kwargs.get("subscription_id"), - resource_group, - name, - "probes", - kwargs["load_balancing_rules"][idx]["probe"], - ) - } - - if isinstance(kwargs.get("inbound_nat_rules"), list): - for idx in range(0, len(kwargs["inbound_nat_rules"])): - # Link to sub-objects which might be created at the same time as the load balancer - if "frontend_ip_configuration" in kwargs["inbound_nat_rules"][idx]: - kwargs["inbound_nat_rules"][idx]["frontend_ip_configuration"] = { - "id": id_url.format( - kwargs.get("subscription_id"), - resource_group, - name, - "frontendIPConfigurations", - kwargs["inbound_nat_rules"][idx]["frontend_ip_configuration"], - ) - } - - if isinstance(kwargs.get("inbound_nat_pools"), list): - for idx in range(0, len(kwargs["inbound_nat_pools"])): - # Link to sub-objects which might be created at the same time as the load balancer - if "frontend_ip_configuration" in kwargs["inbound_nat_pools"][idx]: - kwargs["inbound_nat_pools"][idx]["frontend_ip_configuration"] = { - "id": id_url.format( - kwargs.get("subscription_id"), - resource_group, - name, - "frontendIPConfigurations", - kwargs["inbound_nat_pools"][idx]["frontend_ip_configuration"], - ) - } - - if isinstance(kwargs.get("outbound_nat_rules"), list): - for idx in range(0, len(kwargs["outbound_nat_rules"])): - # Link to sub-objects which might be created at the same time as the load balancer - if "frontend_ip_configuration" in kwargs["outbound_nat_rules"][idx]: - kwargs["outbound_nat_rules"][idx]["frontend_ip_configuration"] = { - "id": id_url.format( - kwargs.get("subscription_id"), - resource_group, - name, - "frontendIPConfigurations", - kwargs["outbound_nat_rules"][idx]["frontend_ip_configuration"], - ) - } - if "backend_address_pool" in kwargs["outbound_nat_rules"][idx]: - kwargs["outbound_nat_rules"][idx]["backend_address_pool"] = { - "id": id_url.format( - kwargs.get("subscription_id"), - resource_group, - name, - "backendAddressPools", - kwargs["outbound_nat_rules"][idx]["backend_address_pool"], - ) - } - - try: - lbmodel = __utils__["azurearm.create_object_model"]( - "network", "LoadBalancer", **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - load_balancer = netconn.load_balancers.create_or_update( - resource_group_name=resource_group, - load_balancer_name=name, - parameters=lbmodel, - ) - load_balancer.wait() - lb_result = load_balancer.result() - result = lb_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def load_balancer_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a load balancer. - - :param name: The name of the load balancer to delete. - - :param resource_group: The resource group name assigned to the - load balancer. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.load_balancer_delete testlb testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - load_balancer = netconn.load_balancers.delete( - load_balancer_name=name, resource_group_name=resource_group - ) - load_balancer.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def usages_list(location, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List subscription network usage for a location. - - :param location: The Azure location to query for network usage. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.usages_list westus - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - result = __utils__["azurearm.paged_object_to_list"]( - netconn.usages.list(location) - ) - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def network_interface_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a network interface. - - :param name: The name of the network interface to delete. - - :param resource_group: The resource group name assigned to the - network interface. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_interface_delete test-iface0 testgroup - - """ - result = False - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - nic = netconn.network_interfaces.delete( - network_interface_name=name, resource_group_name=resource_group - ) - nic.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def network_interface_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific network interface. - - :param name: The name of the network interface to query. - - :param resource_group: The resource group name assigned to the - network interface. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_interface_get test-iface0 testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - nic = netconn.network_interfaces.get( - network_interface_name=name, resource_group_name=resource_group - ) - result = nic.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -# pylint: disable=invalid-name -@_deprecation_message -def network_interface_create_or_update( - name, ip_configurations, subnet, virtual_network, resource_group, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Create or update a network interface within a specified resource group. - - :param name: The name of the network interface to create. - - :param ip_configurations: A list of dictionaries representing valid - NetworkInterfaceIPConfiguration objects. The 'name' key is required at - minimum. At least one IP Configuration must be present. - - :param subnet: The name of the subnet assigned to the network interface. - - :param virtual_network: The name of the virtual network assigned to the subnet. - - :param resource_group: The resource group name assigned to the - virtual network. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_interface_create_or_update test-iface0 [{'name': 'testipconfig1'}] \ - testsubnet testnet testgroup - - """ - if "location" not in kwargs: - rg_props = __salt__["azurearm_resource.resource_group_get"]( - resource_group, **kwargs - ) - - if "error" in rg_props: - log.error("Unable to determine location from resource group specified.") - return False - kwargs["location"] = rg_props["location"] - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - # Use NSG name to link to the ID of an existing NSG. - if kwargs.get("network_security_group"): - nsg = network_security_group_get( - name=kwargs["network_security_group"], - resource_group=resource_group, - **kwargs - ) - if "error" not in nsg: - kwargs["network_security_group"] = {"id": str(nsg["id"])} - - # Use VM name to link to the ID of an existing VM. - if kwargs.get("virtual_machine"): - vm_instance = __salt__["azurearm_compute.virtual_machine_get"]( - name=kwargs["virtual_machine"], resource_group=resource_group, **kwargs - ) - if "error" not in vm_instance: - kwargs["virtual_machine"] = {"id": str(vm_instance["id"])} - - # Loop through IP Configurations and build each dictionary to pass to model creation. - if isinstance(ip_configurations, list): - subnet = subnet_get( - name=subnet, - virtual_network=virtual_network, - resource_group=resource_group, - **kwargs - ) - if "error" not in subnet: - subnet = {"id": str(subnet["id"])} - for ipconfig in ip_configurations: - if "name" in ipconfig: - ipconfig["subnet"] = subnet - if isinstance( - ipconfig.get("application_gateway_backend_address_pools"), list - ): - # TODO: Add ID lookup for referenced object names - pass - if isinstance( - ipconfig.get("load_balancer_backend_address_pools"), list - ): - # TODO: Add ID lookup for referenced object names - pass - if isinstance( - ipconfig.get("load_balancer_inbound_nat_rules"), list - ): - # TODO: Add ID lookup for referenced object names - pass - if ipconfig.get("public_ip_address"): - pub_ip = public_ip_address_get( - name=ipconfig["public_ip_address"], - resource_group=resource_group, - **kwargs - ) - if "error" not in pub_ip: - ipconfig["public_ip_address"] = {"id": str(pub_ip["id"])} - - try: - nicmodel = __utils__["azurearm.create_object_model"]( - "network", "NetworkInterface", ip_configurations=ip_configurations, **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - interface = netconn.network_interfaces.create_or_update( - resource_group_name=resource_group, - network_interface_name=name, - parameters=nicmodel, - ) - interface.wait() - nic_result = interface.result() - result = nic_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def network_interfaces_list_all(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all network interfaces within a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_interfaces_list_all - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - nics = __utils__["azurearm.paged_object_to_list"]( - netconn.network_interfaces.list_all() - ) - - for nic in nics: - result[nic["name"]] = nic - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def network_interfaces_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all network interfaces within a resource group. - - :param resource_group: The resource group name to list network - interfaces within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_interfaces_list testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - nics = __utils__["azurearm.paged_object_to_list"]( - netconn.network_interfaces.list(resource_group_name=resource_group) - ) - - for nic in nics: - result[nic["name"]] = nic - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -# pylint: disable=invalid-name -@_deprecation_message -def network_interface_get_effective_route_table(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get all route tables for a specific network interface. - - :param name: The name of the network interface to query. - - :param resource_group: The resource group name assigned to the - network interface. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_interface_get_effective_route_table test-iface0 testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - nic = netconn.network_interfaces.get_effective_route_table( - network_interface_name=name, resource_group_name=resource_group - ) - nic.wait() - tables = nic.result() - tables = tables.as_dict() - result = tables["value"] - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -# pylint: disable=invalid-name -@_deprecation_message -def network_interface_list_effective_network_security_groups( - name, resource_group, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Get all network security groups applied to a specific network interface. - - :param name: The name of the network interface to query. - - :param resource_group: The resource group name assigned to the - network interface. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.network_interface_list_effective_network_security_groups test-iface0 testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - nic = netconn.network_interfaces.list_effective_network_security_groups( - network_interface_name=name, resource_group_name=resource_group - ) - nic.wait() - groups = nic.result() - groups = groups.as_dict() - result = groups["value"] - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -# pylint: disable=invalid-name -@_deprecation_message -def list_virtual_machine_scale_set_vm_network_interfaces( - scale_set, vm_index, resource_group, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Get information about all network interfaces in a specific virtual machine within a scale set. - - :param scale_set: The name of the scale set to query. - - :param vm_index: The virtual machine index. - - :param resource_group: The resource group name assigned to the - scale set. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.list_virtual_machine_scale_set_vm_network_interfaces testset testvm testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - nics = __utils__["azurearm.paged_object_to_list"]( - netconn.network_interfaces.list_virtual_machine_scale_set_vm_network_interfaces( - virtual_machine_scale_set_name=scale_set, - virtualmachine_index=vm_index, - resource_group_name=resource_group, - ) - ) - - for nic in nics: - result[nic["name"]] = nic - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -# pylint: disable=invalid-name -@_deprecation_message -def list_virtual_machine_scale_set_network_interfaces( - scale_set, resource_group, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Get information about all network interfaces within a scale set. - - :param scale_set: The name of the scale set to query. - - :param resource_group: The resource group name assigned to the - scale set. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.list_virtual_machine_scale_set_vm_network_interfaces testset testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - nics = __utils__["azurearm.paged_object_to_list"]( - netconn.network_interfaces.list_virtual_machine_scale_set_network_interfaces( - virtual_machine_scale_set_name=scale_set, - resource_group_name=resource_group, - ) - ) - - for nic in nics: - result[nic["name"]] = nic - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -# pylint: disable=invalid-name -@_deprecation_message -def get_virtual_machine_scale_set_network_interface( - name, scale_set, vm_index, resource_group, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Get information about a specific network interface within a scale set. - - :param name: The name of the network interface to query. - - :param scale_set: The name of the scale set containing the interface. - - :param vm_index: The virtual machine index. - - :param resource_group: The resource group name assigned to the - scale set. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.get_virtual_machine_scale_set_network_interface test-iface0 testset testvm testgroup - - """ - expand = kwargs.get("expand") - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - nic = netconn.network_interfaces.list_virtual_machine_scale_set_vm_network_interfaces( - network_interface_name=name, - virtual_machine_scale_set_name=scale_set, - virtualmachine_index=vm_index, - resource_group_name=resource_group, - exapnd=expand, - ) - - result = nic.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def public_ip_address_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a public IP address. - - :param name: The name of the public IP address to delete. - - :param resource_group: The resource group name assigned to the - public IP address. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.public_ip_address_delete test-pub-ip testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - pub_ip = netconn.public_ip_addresses.delete( - public_ip_address_name=name, resource_group_name=resource_group - ) - pub_ip.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def public_ip_address_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific public IP address. - - :param name: The name of the public IP address to query. - - :param resource_group: The resource group name assigned to the - public IP address. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.public_ip_address_get test-pub-ip testgroup - - """ - expand = kwargs.get("expand") - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - pub_ip = netconn.public_ip_addresses.get( - public_ip_address_name=name, - resource_group_name=resource_group, - expand=expand, - ) - result = pub_ip.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def public_ip_address_create_or_update(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Create or update a public IP address within a specified resource group. - - :param name: The name of the public IP address to create. - - :param resource_group: The resource group name assigned to the - public IP address. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.public_ip_address_create_or_update test-ip-0 testgroup - - """ - if "location" not in kwargs: - rg_props = __salt__["azurearm_resource.resource_group_get"]( - resource_group, **kwargs - ) - - if "error" in rg_props: - log.error("Unable to determine location from resource group specified.") - return False - kwargs["location"] = rg_props["location"] - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - pub_ip_model = __utils__["azurearm.create_object_model"]( - "network", "PublicIPAddress", **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - ip = netconn.public_ip_addresses.create_or_update( - resource_group_name=resource_group, - public_ip_address_name=name, - parameters=pub_ip_model, - ) - ip.wait() - ip_result = ip.result() - result = ip_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def public_ip_addresses_list_all(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all public IP addresses within a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.public_ip_addresses_list_all - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - pub_ips = __utils__["azurearm.paged_object_to_list"]( - netconn.public_ip_addresses.list_all() - ) - - for ip in pub_ips: - result[ip["name"]] = ip - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def public_ip_addresses_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all public IP addresses within a resource group. - - :param resource_group: The resource group name to list public IP - addresses within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.public_ip_addresses_list testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - pub_ips = __utils__["azurearm.paged_object_to_list"]( - netconn.public_ip_addresses.list(resource_group_name=resource_group) - ) - - for ip in pub_ips: - result[ip["name"]] = ip - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_filter_rule_delete(name, route_filter, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a route filter rule. - - :param name: The route filter rule to delete. - - :param route_filter: The route filter containing the rule. - - :param resource_group: The resource group name assigned to the - route filter. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_filter_rule_delete test-rule test-filter testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - rule = netconn.route_filter_rules.delete( - resource_group_name=resource_group, - route_filter_name=route_filter, - rule_name=name, - ) - rule.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def route_filter_rule_get(name, route_filter, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific route filter rule. - - :param name: The route filter rule to query. - - :param route_filter: The route filter containing the rule. - - :param resource_group: The resource group name assigned to the - route filter. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_filter_rule_get test-rule test-filter testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - rule = netconn.route_filter_rules.get( - resource_group_name=resource_group, - route_filter_name=route_filter, - rule_name=name, - ) - - result = rule.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_filter_rule_create_or_update( - name, access, communities, route_filter, resource_group, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Create or update a rule within a specified route filter. - - :param name: The name of the rule to create. - - :param access: The access type of the rule. Valid values are 'Allow' and 'Deny'. - - :param communities: A list of BGP communities to filter on. - - :param route_filter: The name of the route filter containing the rule. - - :param resource_group: The resource group name assigned to the - route filter. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_filter_rule_create_or_update \ - test-rule allow "['12076:51006']" test-filter testgroup - - """ - if not isinstance(communities, list): - log.error("The communities parameter must be a list of strings!") - return False - - if "location" not in kwargs: - rg_props = __salt__["azurearm_resource.resource_group_get"]( - resource_group, **kwargs - ) - - if "error" in rg_props: - log.error("Unable to determine location from resource group specified.") - return False - kwargs["location"] = rg_props["location"] - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - rule_model = __utils__["azurearm.create_object_model"]( - "network", - "RouteFilterRule", - access=access, - communities=communities, - **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - rule = netconn.route_filter_rules.create_or_update( - resource_group_name=resource_group, - route_filter_name=route_filter, - rule_name=name, - route_filter_rule_parameters=rule_model, - ) - rule.wait() - rule_result = rule.result() - result = rule_result.as_dict() - except CloudError as exc: - message = str(exc) - if kwargs.get("subscription_id") == str(message).strip(): - message = "Subscription not authorized for this operation!" - __utils__["azurearm.log_cloud_error"]("network", message, **kwargs) - result = {"error": message} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def route_filter_rules_list(route_filter, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all routes within a route filter. - - :param route_filter: The route filter to query. - - :param resource_group: The resource group name assigned to the - route filter. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_filter_rules_list test-filter testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - rules = __utils__["azurearm.paged_object_to_list"]( - netconn.route_filter_rules.list_by_route_filter( - resource_group_name=resource_group, route_filter_name=route_filter - ) - ) - - for rule in rules: - result[rule["name"]] = rule - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_filter_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a route filter. - - :param name: The name of the route filter to delete. - - :param resource_group: The resource group name assigned to the - route filter. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_filter_delete test-filter testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - route_filter = netconn.route_filters.delete( - route_filter_name=name, resource_group_name=resource_group - ) - route_filter.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def route_filter_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific route filter. - - :param name: The name of the route table to query. - - :param resource_group: The resource group name assigned to the - route filter. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_filter_get test-filter testgroup - - """ - expand = kwargs.get("expand") - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - route_filter = netconn.route_filters.get( - route_filter_name=name, resource_group_name=resource_group, expand=expand - ) - result = route_filter.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_filter_create_or_update(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Create or update a route filter within a specified resource group. - - :param name: The name of the route filter to create. - - :param resource_group: The resource group name assigned to the - route filter. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_filter_create_or_update test-filter testgroup - - """ - if "location" not in kwargs: - rg_props = __salt__["azurearm_resource.resource_group_get"]( - resource_group, **kwargs - ) - - if "error" in rg_props: - log.error("Unable to determine location from resource group specified.") - return False - kwargs["location"] = rg_props["location"] - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - rt_filter_model = __utils__["azurearm.create_object_model"]( - "network", "RouteFilter", **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - rt_filter = netconn.route_filters.create_or_update( - resource_group_name=resource_group, - route_filter_name=name, - route_filter_parameters=rt_filter_model, - ) - rt_filter.wait() - rt_result = rt_filter.result() - result = rt_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def route_filters_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all route filters within a resource group. - - :param resource_group: The resource group name to list route - filters within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_filters_list testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - filters = __utils__["azurearm.paged_object_to_list"]( - netconn.route_filters.list_by_resource_group( - resource_group_name=resource_group - ) - ) - - for route_filter in filters: - result[route_filter["name"]] = route_filter - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_filters_list_all(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all route filters within a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_filters_list_all - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - filters = __utils__["azurearm.paged_object_to_list"]( - netconn.route_filters.list() - ) - - for route_filter in filters: - result[route_filter["name"]] = route_filter - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_delete(name, route_table, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a route from a route table. - - :param name: The route to delete. - - :param route_table: The route table containing the route. - - :param resource_group: The resource group name assigned to the - route table. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_delete test-rt test-rt-table testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - route = netconn.routes.delete( - resource_group_name=resource_group, - route_table_name=route_table, - route_name=name, - ) - route.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def route_get(name, route_table, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific route. - - :param name: The route to query. - - :param route_table: The route table containing the route. - - :param resource_group: The resource group name assigned to the - route table. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_get test-rt test-rt-table testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - route = netconn.routes.get( - resource_group_name=resource_group, - route_table_name=route_table, - route_name=name, - ) - - result = route.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_create_or_update( - name, - address_prefix, - next_hop_type, - route_table, - resource_group, - next_hop_ip_address=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Create or update a route within a specified route table. - - :param name: The name of the route to create. - - :param address_prefix: The destination CIDR to which the route applies. - - :param next_hop_type: The type of Azure hop the packet should be sent to. Possible values are: - 'VirtualNetworkGateway', 'VnetLocal', 'Internet', 'VirtualAppliance', and 'None'. - - :param next_hop_ip_address: Optional IP address to which packets should be forwarded. Next hop - values are only allowed in routes where the next_hop_type is 'VirtualAppliance'. - - :param route_table: The name of the route table containing the route. - - :param resource_group: The resource group name assigned to the - route table. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_create_or_update test-rt '10.0.0.0/8' test-rt-table testgroup - - """ - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - rt_model = __utils__["azurearm.create_object_model"]( - "network", - "Route", - address_prefix=address_prefix, - next_hop_type=next_hop_type, - next_hop_ip_address=next_hop_ip_address, - **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - route = netconn.routes.create_or_update( - resource_group_name=resource_group, - route_table_name=route_table, - route_name=name, - route_parameters=rt_model, - ) - route.wait() - rt_result = route.result() - result = rt_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def routes_list(route_table, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all routes within a route table. - - :param route_table: The route table to query. - - :param resource_group: The resource group name assigned to the - route table. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.routes_list test-rt-table testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - routes = __utils__["azurearm.paged_object_to_list"]( - netconn.routes.list( - resource_group_name=resource_group, route_table_name=route_table - ) - ) - - for route in routes: - result[route["name"]] = route - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_table_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a route table. - - :param name: The name of the route table to delete. - - :param resource_group: The resource group name assigned to the - route table. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_table_delete test-rt-table testgroup - - """ - result = False - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - table = netconn.route_tables.delete( - route_table_name=name, resource_group_name=resource_group - ) - table.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - - return result - - -@_deprecation_message -def route_table_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific route table. - - :param name: The name of the route table to query. - - :param resource_group: The resource group name assigned to the - route table. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_table_get test-rt-table testgroup - - """ - expand = kwargs.get("expand") - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - table = netconn.route_tables.get( - route_table_name=name, resource_group_name=resource_group, expand=expand - ) - result = table.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_table_create_or_update(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Create or update a route table within a specified resource group. - - :param name: The name of the route table to create. - - :param resource_group: The resource group name assigned to the - route table. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_table_create_or_update test-rt-table testgroup - - """ - if "location" not in kwargs: - rg_props = __salt__["azurearm_resource.resource_group_get"]( - resource_group, **kwargs - ) - - if "error" in rg_props: - log.error("Unable to determine location from resource group specified.") - return False - kwargs["location"] = rg_props["location"] - - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - - try: - rt_tbl_model = __utils__["azurearm.create_object_model"]( - "network", "RouteTable", **kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - table = netconn.route_tables.create_or_update( - resource_group_name=resource_group, - route_table_name=name, - parameters=rt_tbl_model, - ) - table.wait() - tbl_result = table.result() - result = tbl_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def route_tables_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all route tables within a resource group. - - :param resource_group: The resource group name to list route - tables within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_tables_list testgroup - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - tables = __utils__["azurearm.paged_object_to_list"]( - netconn.route_tables.list(resource_group_name=resource_group) - ) - - for table in tables: - result[table["name"]] = table - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def route_tables_list_all(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all route tables within a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_network.route_tables_list_all - - """ - result = {} - netconn = __utils__["azurearm.get_client"]("network", **kwargs) - try: - tables = __utils__["azurearm.paged_object_to_list"]( - netconn.route_tables.list_all() - ) - - for table in tables: - result[table["name"]] = table - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("network", str(exc), **kwargs) - result = {"error": str(exc)} - - return result diff --git a/salt/modules/azurearm_resource.py b/salt/modules/azurearm_resource.py deleted file mode 100644 index b1b865a81d1..00000000000 --- a/salt/modules/azurearm_resource.py +++ /dev/null @@ -1,1253 +0,0 @@ -""" -Azure (ARM) Resource Execution Module - -.. versionadded:: 2019.2.0 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -:maintainer: -:maturity: new -:depends: - * `azure `_ >= 2.0.0 - * `azure-common `_ >= 1.1.8 - * `azure-mgmt `_ >= 1.0.0 - * `azure-mgmt-compute `_ >= 1.0.0 - * `azure-mgmt-network `_ >= 1.7.1 - * `azure-mgmt-resource `_ >= 1.1.0 - * `azure-mgmt-storage `_ >= 1.0.0 - * `azure-mgmt-web `_ >= 0.32.0 - * `azure-storage `_ >= 0.34.3 - * `msrestazure `_ >= 0.4.21 -:platform: linux - -:configuration: This module requires Azure Resource Manager credentials to be passed as keyword arguments - to every function in order to work properly. - - Required provider parameters: - - if using username and password: - * ``subscription_id`` - * ``username`` - * ``password`` - - if using a service principal: - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - - Optional provider parameters: - -**cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. - Possible values: - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` - -""" - -# Python libs - -import logging -from functools import wraps - -# Salt Libs -import salt.utils.azurearm -import salt.utils.json - -# Azure libs -HAS_LIBS = False -try: - import azure.mgmt.resource.resources.models # pylint: disable=unused-import - from msrest.exceptions import SerializationError - from msrestazure.azure_exceptions import CloudError - - HAS_LIBS = True -except ImportError: - pass - -__virtualname__ = "azurearm_resource" - -log = logging.getLogger(__name__) - - -def __virtual__(): - if not HAS_LIBS: - return ( - False, - "The following dependencies are required to use the AzureARM modules: " - "Microsoft Azure SDK for Python >= 2.0rc6, " - "MS REST Azure (msrestazure) >= 0.4", - ) - - return __virtualname__ - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about azurearm deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "The 'azurearm' functionality in Salt has been deprecated and its " - "functionality will be removed in version 3007 in favor of the " - "saltext.azurerm Salt Extension. " - "(https://github.com/salt-extensions/saltext-azurerm)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -@_deprecation_message -def resource_groups_list(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all resource groups within a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.resource_groups_list - - """ - result = {} - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - groups = __utils__["azurearm.paged_object_to_list"]( - resconn.resource_groups.list() - ) - - for group in groups: - result[group["name"]] = group - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def resource_group_check_existence(name, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Check for the existence of a named resource group in the current subscription. - - :param name: The resource group name to check. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.resource_group_check_existence testgroup - - """ - result = False - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - result = resconn.resource_groups.check_existence(name) - - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - - return result - - -@_deprecation_message -def resource_group_get(name, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get a dictionary representing a resource group's properties. - - :param name: The resource group name to get. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.resource_group_get testgroup - - """ - result = {} - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - group = resconn.resource_groups.get(name) - result = group.as_dict() - - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def resource_group_create_or_update( - name, location, **kwargs -): # pylint: disable=invalid-name - """ - .. versionadded:: 2019.2.0 - - Create or update a resource group in a given location. - - :param name: The name of the resource group to create or update. - - :param location: The location of the resource group. This value - is not able to be updated once the resource group is created. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.resource_group_create_or_update testgroup westus - - """ - result = {} - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - resource_group_params = { - "location": location, - "managed_by": kwargs.get("managed_by"), - "tags": kwargs.get("tags"), - } - try: - group = resconn.resource_groups.create_or_update(name, resource_group_params) - result = group.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def resource_group_delete(name, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a resource group from the subscription. - - :param name: The resource group name to delete. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.resource_group_delete testgroup - - """ - result = False - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - group = resconn.resource_groups.delete(name) - group.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - - return result - - -@_deprecation_message -def deployment_operation_get(operation, deployment, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get a deployment operation within a deployment. - - :param operation: The operation ID of the operation within the deployment. - - :param deployment: The name of the deployment containing the operation. - - :param resource_group: The resource group name assigned to the - deployment. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployment_operation_get XXXXX testdeploy testgroup - - """ - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - operation = resconn.deployment_operations.get( - resource_group_name=resource_group, - deployment_name=deployment, - operation_id=operation, - ) - - result = operation.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def deployment_operations_list(name, resource_group, result_limit=10, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all deployment operations within a deployment. - - :param name: The name of the deployment to query. - - :param resource_group: The resource group name assigned to the - deployment. - - :param result_limit: (Default: 10) The limit on the list of deployment - operations. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployment_operations_list testdeploy testgroup - - """ - result = {} - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - operations = __utils__["azurearm.paged_object_to_list"]( - resconn.deployment_operations.list( - resource_group_name=resource_group, - deployment_name=name, - top=result_limit, - ) - ) - - for oper in operations: - result[oper["operation_id"]] = oper - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def deployment_delete(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a deployment. - - :param name: The name of the deployment to delete. - - :param resource_group: The resource group name assigned to the - deployment. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployment_delete testdeploy testgroup - - """ - result = False - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - deploy = resconn.deployments.delete( - deployment_name=name, resource_group_name=resource_group - ) - deploy.wait() - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - - return result - - -@_deprecation_message -def deployment_check_existence(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Check the existence of a deployment. - - :param name: The name of the deployment to query. - - :param resource_group: The resource group name assigned to the - deployment. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployment_check_existence testdeploy testgroup - - """ - result = False - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - result = resconn.deployments.check_existence( - deployment_name=name, resource_group_name=resource_group - ) - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - - return result - - -@_deprecation_message -def deployment_create_or_update( - name, - resource_group, - deploy_mode="incremental", - debug_setting="none", - deploy_params=None, - parameters_link=None, - deploy_template=None, - template_link=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Deploys resources to a resource group. - - :param name: The name of the deployment to create or update. - - :param resource_group: The resource group name assigned to the - deployment. - - :param deploy_mode: The mode that is used to deploy resources. This value can be either - 'incremental' or 'complete'. In Incremental mode, resources are deployed without deleting - existing resources that are not included in the template. In Complete mode, resources - are deployed and existing resources in the resource group that are not included in - the template are deleted. Be careful when using Complete mode as you may - unintentionally delete resources. - - :param debug_setting: The debug setting of the deployment. The permitted values are 'none', - 'requestContent', 'responseContent', or 'requestContent,responseContent'. By logging - information about the request or response, you could potentially expose sensitive data - that is retrieved through the deployment operations. - - :param deploy_params: JSON string containing name and value pairs that define the deployment - parameters for the template. You use this element when you want to provide the parameter - values directly in the request rather than link to an existing parameter file. Use either - the parameters_link property or the deploy_params property, but not both. - - :param parameters_link: The URI of a parameters file. You use this element to link to an existing - parameters file. Use either the parameters_link property or the deploy_params property, but not both. - - :param deploy_template: JSON string of template content. You use this element when you want to pass - the template syntax directly in the request rather than link to an existing template. Use either - the template_link property or the deploy_template property, but not both. - - :param template_link: The URI of the template. Use either the template_link property or the - deploy_template property, but not both. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployment_create_or_update testdeploy testgroup - - """ - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - - prop_kwargs = {"mode": deploy_mode} - prop_kwargs["debug_setting"] = {"detail_level": debug_setting} - - if deploy_params: - prop_kwargs["parameters"] = deploy_params - else: - if isinstance(parameters_link, dict): - prop_kwargs["parameters_link"] = parameters_link - else: - prop_kwargs["parameters_link"] = {"uri": parameters_link} - - if deploy_template: - prop_kwargs["template"] = deploy_template - else: - if isinstance(template_link, dict): - prop_kwargs["template_link"] = template_link - else: - prop_kwargs["template_link"] = {"uri": template_link} - - deploy_kwargs = kwargs.copy() - deploy_kwargs.update(prop_kwargs) - - try: - deploy_model = __utils__["azurearm.create_object_model"]( - "resource", "DeploymentProperties", **deploy_kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - validate = deployment_validate( - name=name, resource_group=resource_group, **deploy_kwargs - ) - if "error" in validate: - result = validate - else: - deploy = resconn.deployments.create_or_update( - deployment_name=name, - resource_group_name=resource_group, - properties=deploy_model, - ) - deploy.wait() - deploy_result = deploy.result() - result = deploy_result.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def deployment_get(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific deployment. - - :param name: The name of the deployment to query. - - :param resource_group: The resource group name assigned to the - deployment. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployment_get testdeploy testgroup - - """ - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - deploy = resconn.deployments.get( - deployment_name=name, resource_group_name=resource_group - ) - result = deploy.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def deployment_cancel(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Cancel a deployment if in 'Accepted' or 'Running' state. - - :param name: The name of the deployment to cancel. - - :param resource_group: The resource group name assigned to the - deployment. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployment_cancel testdeploy testgroup - - """ - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - resconn.deployments.cancel( - deployment_name=name, resource_group_name=resource_group - ) - result = {"result": True} - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc), "result": False} - - return result - - -@_deprecation_message -def deployment_validate( - name, - resource_group, - deploy_mode=None, - debug_setting=None, - deploy_params=None, - parameters_link=None, - deploy_template=None, - template_link=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Validates whether the specified template is syntactically correct - and will be accepted by Azure Resource Manager. - - :param name: The name of the deployment to validate. - - :param resource_group: The resource group name assigned to the - deployment. - - :param deploy_mode: The mode that is used to deploy resources. This value can be either - 'incremental' or 'complete'. In Incremental mode, resources are deployed without deleting - existing resources that are not included in the template. In Complete mode, resources - are deployed and existing resources in the resource group that are not included in - the template are deleted. Be careful when using Complete mode as you may - unintentionally delete resources. - - :param debug_setting: The debug setting of the deployment. The permitted values are 'none', - 'requestContent', 'responseContent', or 'requestContent,responseContent'. By logging - information about the request or response, you could potentially expose sensitive data - that is retrieved through the deployment operations. - - :param deploy_params: JSON string containing name and value pairs that define the deployment - parameters for the template. You use this element when you want to provide the parameter - values directly in the request rather than link to an existing parameter file. Use either - the parameters_link property or the deploy_params property, but not both. - - :param parameters_link: The URI of a parameters file. You use this element to link to an existing - parameters file. Use either the parameters_link property or the deploy_params property, but not both. - - :param deploy_template: JSON string of template content. You use this element when you want to pass - the template syntax directly in the request rather than link to an existing template. Use either - the template_link property or the deploy_template property, but not both. - - :param template_link: The URI of the template. Use either the template_link property or the - deploy_template property, but not both. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployment_validate testdeploy testgroup - - """ - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - - prop_kwargs = {"mode": deploy_mode} - prop_kwargs["debug_setting"] = {"detail_level": debug_setting} - - if deploy_params: - prop_kwargs["parameters"] = deploy_params - else: - if isinstance(parameters_link, dict): - prop_kwargs["parameters_link"] = parameters_link - else: - prop_kwargs["parameters_link"] = {"uri": parameters_link} - - if deploy_template: - prop_kwargs["template"] = deploy_template - else: - if isinstance(template_link, dict): - prop_kwargs["template_link"] = template_link - else: - prop_kwargs["template_link"] = {"uri": template_link} - - deploy_kwargs = kwargs.copy() - deploy_kwargs.update(prop_kwargs) - - try: - deploy_model = __utils__["azurearm.create_object_model"]( - "resource", "DeploymentProperties", **deploy_kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - local_validation = deploy_model.validate() - if local_validation: - raise local_validation[0] - - deploy = resconn.deployments.validate( - deployment_name=name, - resource_group_name=resource_group, - properties=deploy_model, - ) - result = deploy.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def deployment_export_template(name, resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Exports the template used for the specified deployment. - - :param name: The name of the deployment to query. - - :param resource_group: The resource group name assigned to the - deployment. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployment_export_template testdeploy testgroup - - """ - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - deploy = resconn.deployments.export_template( - deployment_name=name, resource_group_name=resource_group - ) - result = deploy.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def deployments_list(resource_group, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all deployments within a resource group. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.deployments_list testgroup - - """ - result = {} - resconn = __utils__["azurearm.get_client"]("resource", **kwargs) - try: - deployments = __utils__["azurearm.paged_object_to_list"]( - resconn.deployments.list_by_resource_group( - resource_group_name=resource_group - ) - ) - - for deploy in deployments: - result[deploy["name"]] = deploy - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def subscriptions_list_locations(subscription_id=None, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all locations for a subscription. - - :param subscription_id: The ID of the subscription to query. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.subscriptions_list_locations XXXXXXXX - - """ - result = {} - - if not subscription_id: - subscription_id = kwargs.get("subscription_id") - elif not kwargs.get("subscription_id"): - kwargs["subscription_id"] = subscription_id - - subconn = __utils__["azurearm.get_client"]("subscription", **kwargs) - try: - locations = __utils__["azurearm.paged_object_to_list"]( - subconn.subscriptions.list_locations( - subscription_id=kwargs["subscription_id"] - ) - ) - - for loc in locations: - result[loc["name"]] = loc - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def subscription_get(subscription_id=None, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a subscription. - - :param subscription_id: The ID of the subscription to query. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.subscription_get XXXXXXXX - - """ - result = {} - - if not subscription_id: - subscription_id = kwargs.get("subscription_id") - elif not kwargs.get("subscription_id"): - kwargs["subscription_id"] = subscription_id - - subconn = __utils__["azurearm.get_client"]("subscription", **kwargs) - try: - subscription = subconn.subscriptions.get( - subscription_id=kwargs.get("subscription_id") - ) - - result = subscription.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def subscriptions_list(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all subscriptions for a tenant. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.subscriptions_list - - """ - result = {} - subconn = __utils__["azurearm.get_client"]("subscription", **kwargs) - try: - subs = __utils__["azurearm.paged_object_to_list"](subconn.subscriptions.list()) - - for sub in subs: - result[sub["subscription_id"]] = sub - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def tenants_list(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all tenants for your account. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.tenants_list - - """ - result = {} - subconn = __utils__["azurearm.get_client"]("subscription", **kwargs) - try: - tenants = __utils__["azurearm.paged_object_to_list"](subconn.tenants.list()) - - for tenant in tenants: - result[tenant["tenant_id"]] = tenant - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def policy_assignment_delete(name, scope, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a policy assignment. - - :param name: The name of the policy assignment to delete. - - :param scope: The scope of the policy assignment. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.policy_assignment_delete testassign \ - /subscriptions/bc75htn-a0fhsi-349b-56gh-4fghti-f84852 - - """ - result = False - polconn = __utils__["azurearm.get_client"]("policy", **kwargs) - try: - # pylint: disable=unused-variable - policy = polconn.policy_assignments.delete( - policy_assignment_name=name, scope=scope - ) - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - - return result - - -@_deprecation_message -def policy_assignment_create(name, scope, definition_name, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Create a policy assignment. - - :param name: The name of the policy assignment to create. - - :param scope: The scope of the policy assignment. - - :param definition_name: The name of the policy definition to assign. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.policy_assignment_create testassign \ - /subscriptions/bc75htn-a0fhsi-349b-56gh-4fghti-f84852 testpolicy - - """ - polconn = __utils__["azurearm.get_client"]("policy", **kwargs) - - # "get" doesn't work for built-in policies per https://github.com/Azure/azure-cli/issues/692 - # Uncomment this section when the ticket above is resolved. - # BEGIN - # definition = policy_definition_get( - # name=definition_name, - # **kwargs - # ) - # END - - # Delete this section when the ticket above is resolved. - # BEGIN - definition_list = policy_definitions_list(**kwargs) - if definition_name in definition_list: - definition = definition_list[definition_name] - else: - definition = { - "error": 'The policy definition named "{}" could not be found.'.format( - definition_name - ) - } - # END - - if "error" not in definition: - definition_id = str(definition["id"]) - - prop_kwargs = {"policy_definition_id": definition_id} - - policy_kwargs = kwargs.copy() - policy_kwargs.update(prop_kwargs) - - try: - policy_model = __utils__["azurearm.create_object_model"]( - "resource.policy", "PolicyAssignment", **policy_kwargs - ) - except TypeError as exc: - result = { - "error": "The object model could not be built. ({})".format(str(exc)) - } - return result - - try: - policy = polconn.policy_assignments.create( - scope=scope, policy_assignment_name=name, parameters=policy_model - ) - result = policy.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - else: - result = { - "error": 'The policy definition named "{}" could not be found.'.format( - definition_name - ) - } - - return result - - -@_deprecation_message -def policy_assignment_get(name, scope, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific policy assignment. - - :param name: The name of the policy assignment to query. - - :param scope: The scope of the policy assignment. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.policy_assignment_get testassign \ - /subscriptions/bc75htn-a0fhsi-349b-56gh-4fghti-f84852 - - """ - polconn = __utils__["azurearm.get_client"]("policy", **kwargs) - try: - policy = polconn.policy_assignments.get( - policy_assignment_name=name, scope=scope - ) - result = policy.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def policy_assignments_list_for_resource_group( - resource_group, **kwargs -): # pylint: disable=invalid-name - """ - .. versionadded:: 2019.2.0 - - List all policy assignments for a resource group. - - :param resource_group: The resource group name to list policy assignments within. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.policy_assignments_list_for_resource_group testgroup - - """ - result = {} - polconn = __utils__["azurearm.get_client"]("policy", **kwargs) - try: - policy_assign = __utils__["azurearm.paged_object_to_list"]( - polconn.policy_assignments.list_for_resource_group( - resource_group_name=resource_group, filter=kwargs.get("filter") - ) - ) - - for assign in policy_assign: - result[assign["name"]] = assign - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def policy_assignments_list(**kwargs): - """ - .. versionadded:: 2019.2.0 - - List all policy assignments for a subscription. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.policy_assignments_list - - """ - result = {} - polconn = __utils__["azurearm.get_client"]("policy", **kwargs) - try: - policy_assign = __utils__["azurearm.paged_object_to_list"]( - polconn.policy_assignments.list() - ) - - for assign in policy_assign: - result[assign["name"]] = assign - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def policy_definition_create_or_update( - name, policy_rule, **kwargs -): # pylint: disable=invalid-name - """ - .. versionadded:: 2019.2.0 - - Create or update a policy definition. - - :param name: The name of the policy definition to create or update. - - :param policy_rule: A dictionary defining the - `policy rule `_. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.policy_definition_create_or_update testpolicy '{...rule definition..}' - - """ - if not isinstance(policy_rule, dict): - result = {"error": "The policy rule must be a dictionary!"} - return result - - polconn = __utils__["azurearm.get_client"]("policy", **kwargs) - - # Convert OrderedDict to dict - prop_kwargs = { - "policy_rule": salt.utils.json.loads(salt.utils.json.dumps(policy_rule)) - } - - policy_kwargs = kwargs.copy() - policy_kwargs.update(prop_kwargs) - - try: - policy_model = __utils__["azurearm.create_object_model"]( - "resource.policy", "PolicyDefinition", **policy_kwargs - ) - except TypeError as exc: - result = {"error": "The object model could not be built. ({})".format(str(exc))} - return result - - try: - policy = polconn.policy_definitions.create_or_update( - policy_definition_name=name, parameters=policy_model - ) - result = policy.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - except SerializationError as exc: - result = { - "error": "The object model could not be parsed. ({})".format(str(exc)) - } - - return result - - -@_deprecation_message -def policy_definition_delete(name, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Delete a policy definition. - - :param name: The name of the policy definition to delete. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.policy_definition_delete testpolicy - - """ - result = False - polconn = __utils__["azurearm.get_client"]("policy", **kwargs) - try: - # pylint: disable=unused-variable - policy = polconn.policy_definitions.delete(policy_definition_name=name) - result = True - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - - return result - - -@_deprecation_message -def policy_definition_get(name, **kwargs): - """ - .. versionadded:: 2019.2.0 - - Get details about a specific policy definition. - - :param name: The name of the policy definition to query. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.policy_definition_get testpolicy - - """ - polconn = __utils__["azurearm.get_client"]("policy", **kwargs) - try: - policy_def = polconn.policy_definitions.get(policy_definition_name=name) - result = policy_def.as_dict() - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result - - -@_deprecation_message -def policy_definitions_list(hide_builtin=False, **kwargs): - """ - .. versionadded:: 2019.2.0 - - List all policy definitions for a subscription. - - :param hide_builtin: Boolean which will filter out BuiltIn policy definitions from the result. - - CLI Example: - - .. code-block:: bash - - salt-call azurearm_resource.policy_definitions_list - - """ - result = {} - polconn = __utils__["azurearm.get_client"]("policy", **kwargs) - try: - policy_defs = __utils__["azurearm.paged_object_to_list"]( - polconn.policy_definitions.list() - ) - - for policy in policy_defs: - if not (hide_builtin and policy["policy_type"] == "BuiltIn"): - result[policy["name"]] = policy - except CloudError as exc: - __utils__["azurearm.log_cloud_error"]("resource", str(exc), **kwargs) - result = {"error": str(exc)} - - return result diff --git a/salt/pillar/azureblob.py b/salt/pillar/azureblob.py deleted file mode 100644 index 4c26ba14b29..00000000000 --- a/salt/pillar/azureblob.py +++ /dev/null @@ -1,465 +0,0 @@ -""" -Use Azure Blob as a Pillar source. - -.. versionadded:: 3001 - -:maintainer: -:maturity: new -:depends: - * `azure-storage-blob `_ >= 12.0.0 - -The Azure Blob ext_pillar can be configured with the following parameters: - -.. code-block:: yaml - - ext_pillar: - - azureblob: - container: 'test_container' - connection_string: 'connection_string' - multiple_env: False - environment: 'base' - blob_cache_expire: 30 - blob_sync_on_update: True - -:param container: The name of the target Azure Blob Container. - -:param connection_string: The connection string to use to access the specified Azure Blob Container. - -:param multiple_env: Specifies whether the pillar should interpret top level folders as pillar environments. - Defaults to false. - -:param environment: Specifies which environment the container represents when in single environment mode. Defaults - to 'base' and is ignored if multiple_env is set as True. - -:param blob_cache_expire: Specifies expiration time of the Azure Blob metadata cache file. Defaults to 30s. - -:param blob_sync_on_update: Specifies if the cache is synced on update. Defaults to True. - -""" - -import logging -import os -import pickle -import time -from copy import deepcopy - -import salt.utils.files -import salt.utils.hashutils -from salt.pillar import Pillar - -HAS_LIBS = False -try: - # pylint: disable=no-name-in-module - from azure.storage.blob import BlobServiceClient - - # pylint: enable=no-name-in-module - HAS_LIBS = True -except ImportError: - pass - - -__virtualname__ = "azureblob" - -# Set up logging -log = logging.getLogger(__name__) - - -def __virtual__(): - if not HAS_LIBS: - return ( - False, - "The following dependency is required to use the Azure Blob ext_pillar: " - "Microsoft Azure Storage Blob >= 12.0.0 ", - ) - - return __virtualname__ - - -def ext_pillar( - minion_id, - pillar, # pylint: disable=W0613 - container, - connection_string, - multiple_env=False, - environment="base", - blob_cache_expire=30, - blob_sync_on_update=True, -): - """ - Execute a command and read the output as YAML. - - :param container: The name of the target Azure Blob Container. - - :param connection_string: The connection string to use to access the specified Azure Blob Container. - - :param multiple_env: Specifies whether the pillar should interpret top level folders as pillar environments. - Defaults to false. - - :param environment: Specifies which environment the container represents when in single environment mode. Defaults - to 'base' and is ignored if multiple_env is set as True. - - :param blob_cache_expire: Specifies expiration time of the Azure Blob metadata cache file. Defaults to 30s. - - :param blob_sync_on_update: Specifies if the cache is synced on update. Defaults to True. - - """ - # normpath is needed to remove appended '/' if root is empty string. - pillar_dir = os.path.normpath( - os.path.join(_get_cache_dir(), environment, container) - ) - - if __opts__["pillar_roots"].get(environment, []) == [pillar_dir]: - return {} - - metadata = _init( - connection_string, container, multiple_env, environment, blob_cache_expire - ) - - log.debug("Blob metadata: %s", metadata) - - if blob_sync_on_update: - # sync the containers to the local cache - log.info("Syncing local pillar cache from Azure Blob...") - for saltenv, env_meta in metadata.items(): - for container, files in _find_files(env_meta).items(): - for file_path in files: - cached_file_path = _get_cached_file_name( - container, saltenv, file_path - ) - log.info("%s - %s : %s", container, saltenv, file_path) - # load the file from Azure Blob if not in the cache or too old - _get_file_from_blob( - connection_string, - metadata, - saltenv, - container, - file_path, - cached_file_path, - ) - - log.info("Sync local pillar cache from Azure Blob completed.") - - opts = deepcopy(__opts__) - opts["pillar_roots"][environment] = ( - [os.path.join(pillar_dir, environment)] if multiple_env else [pillar_dir] - ) - - # Avoid recursively re-adding this same pillar - opts["ext_pillar"] = [x for x in opts["ext_pillar"] if "azureblob" not in x] - - pil = Pillar(opts, __grains__, minion_id, environment) - - compiled_pillar = pil.compile_pillar(ext=False) - - return compiled_pillar - - -def _init(connection_string, container, multiple_env, environment, blob_cache_expire): - """ - .. versionadded:: 3001 - - Connect to Blob Storage and download the metadata for each file in all containers specified and - cache the data to disk. - - :param connection_string: The connection string to use to access the specified Azure Blob Container. - - :param container: The name of the target Azure Blob Container. - - :param multiple_env: Specifies whether the pillar should interpret top level folders as pillar environments. - Defaults to false. - - :param environment: Specifies which environment the container represents when in single environment mode. Defaults - to 'base' and is ignored if multiple_env is set as True. - - :param blob_cache_expire: Specifies expiration time of the Azure Blob metadata cache file. Defaults to 30s. - - """ - cache_file = _get_containers_cache_filename(container) - exp = time.time() - blob_cache_expire - - # Check if cache_file exists and its mtime - if os.path.isfile(cache_file): - cache_file_mtime = os.path.getmtime(cache_file) - else: - # If the file does not exist then set mtime to 0 (aka epoch) - cache_file_mtime = 0 - - expired = cache_file_mtime <= exp - - log.debug( - "Blob storage container cache file %s is %sexpired, mtime_diff=%ss," - " expiration=%ss", - cache_file, - "" if expired else "not ", - cache_file_mtime - exp, - blob_cache_expire, - ) - - if expired: - pillars = _refresh_containers_cache_file( - connection_string, container, cache_file, multiple_env, environment - ) - else: - pillars = _read_containers_cache_file(cache_file) - - log.debug("Blob container retrieved pillars %s", pillars) - - return pillars - - -def _get_cache_dir(): - """ - .. versionadded:: 3001 - - Get pillar cache directory. Initialize it if it does not exist. - - """ - cache_dir = os.path.join(__opts__["cachedir"], "pillar_azureblob") - - if not os.path.isdir(cache_dir): - log.debug("Initializing Azure Blob Pillar Cache") - os.makedirs(cache_dir) - - return cache_dir - - -def _get_cached_file_name(container, saltenv, path): - """ - .. versionadded:: 3001 - - Return the cached file name for a container path file. - - :param container: The name of the target Azure Blob Container. - - :param saltenv: Specifies which environment the container represents. - - :param path: The path of the file in the container. - - """ - file_path = os.path.join(_get_cache_dir(), saltenv, container, path) - - # make sure container and saltenv directories exist - if not os.path.exists(os.path.dirname(file_path)): - os.makedirs(os.path.dirname(file_path)) - - return file_path - - -def _get_containers_cache_filename(container): - """ - .. versionadded:: 3001 - - Return the filename of the cache for container contents. Create the path if it does not exist. - - :param container: The name of the target Azure Blob Container. - - """ - cache_dir = _get_cache_dir() - if not os.path.exists(cache_dir): - os.makedirs(cache_dir) - - return os.path.join(cache_dir, "{}-files.cache".format(container)) - - -def _refresh_containers_cache_file( - connection_string, container, cache_file, multiple_env=False, environment="base" -): - """ - .. versionadded:: 3001 - - Downloads the entire contents of an Azure storage container to the local filesystem. - - :param connection_string: The connection string to use to access the specified Azure Blob Container. - - :param container: The name of the target Azure Blob Container. - - :param cache_file: The path of where the file will be cached. - - :param multiple_env: Specifies whether the pillar should interpret top level folders as pillar environments. - - :param environment: Specifies which environment the container represents when in single environment mode. This is - ignored if multiple_env is set as True. - - """ - try: - # Create the BlobServiceClient object which will be used to create a container client - blob_service_client = BlobServiceClient.from_connection_string( - connection_string - ) - - # Create the ContainerClient object - container_client = blob_service_client.get_container_client(container) - except Exception as exc: # pylint: disable=broad-except - log.error("Exception: %s", exc) - return False - - metadata = {} - - def _walk_blobs(saltenv="base", prefix=None): - # Walk the blobs in the container with a generator - blob_list = container_client.walk_blobs(name_starts_with=prefix) - - # Iterate over the generator - while True: - try: - blob = next(blob_list) - except StopIteration: - break - - log.debug("Raw blob attributes: %s", blob) - - # Directories end with "/". - if blob.name.endswith("/"): - # Recurse into the directory - _walk_blobs(prefix=blob.name) - continue - - if multiple_env: - saltenv = "base" if (not prefix or prefix == ".") else prefix[:-1] - - if saltenv not in metadata: - metadata[saltenv] = {} - - if container not in metadata[saltenv]: - metadata[saltenv][container] = [] - - metadata[saltenv][container].append(blob) - - _walk_blobs(saltenv=environment) - - # write the metadata to disk - if os.path.isfile(cache_file): - os.remove(cache_file) - - log.debug("Writing Azure blobs pillar cache file") - - with salt.utils.files.fopen(cache_file, "wb") as fp_: - pickle.dump(metadata, fp_) - - return metadata - - -def _read_containers_cache_file(cache_file): - """ - .. versionadded:: 3001 - - Return the contents of the containers cache file. - - :param cache_file: The path for where the file will be cached. - - """ - log.debug("Reading containers cache file") - - with salt.utils.files.fopen(cache_file, "rb") as fp_: - data = pickle.load(fp_) - - return data - - -def _find_files(metadata): - """ - .. versionadded:: 3001 - - Looks for all the files in the Azure Blob container cache metadata. - - :param metadata: The metadata for the container files. - - """ - ret = {} - - for container, data in metadata.items(): - if container not in ret: - ret[container] = [] - - # grab the paths from the metadata - file_paths = [k["name"] for k in data] - # filter out the dirs - ret[container] += [k for k in file_paths if not k.endswith("/")] - - return ret - - -def _find_file_meta(metadata, container, saltenv, path): - """ - .. versionadded:: 3001 - - Looks for a file's metadata in the Azure Blob Container cache file. - - :param metadata: The metadata for the container files. - - :param container: The name of the target Azure Blob Container. - - :param saltenv: Specifies which environment the container represents. - - :param path: The path of the file in the container. - - """ - env_meta = metadata[saltenv] if saltenv in metadata else {} - container_meta = env_meta[container] if container in env_meta else {} - - for item_meta in container_meta: - item_meta = dict(item_meta) - if "name" in item_meta and item_meta["name"] == path: - return item_meta - - -def _get_file_from_blob( - connection_string, metadata, saltenv, container, path, cached_file_path -): - """ - .. versionadded:: 3001 - - Downloads the entire contents of an Azure storage container to the local filesystem. - - :param connection_string: The connection string to use to access the specified Azure Blob Container. - - :param metadata: The metadata for the container files. - - :param saltenv: Specifies which environment the container represents when in single environment mode. This is - ignored if multiple_env is set as True. - - :param container: The name of the target Azure Blob Container. - - :param path: The path of the file in the container. - - :param cached_file_path: The path of where the file will be cached. - - """ - # check the local cache... - if os.path.isfile(cached_file_path): - file_meta = _find_file_meta(metadata, container, saltenv, path) - file_md5 = ( - "".join(list(filter(str.isalnum, file_meta["etag"]))) if file_meta else None - ) - - cached_md5 = salt.utils.hashutils.get_hash(cached_file_path, "md5") - - # hashes match we have a cache hit - log.debug( - "Cached file: path=%s, md5=%s, etag=%s", - cached_file_path, - cached_md5, - file_md5, - ) - if cached_md5 == file_md5: - return - - try: - # Create the BlobServiceClient object which will be used to create a container client - blob_service_client = BlobServiceClient.from_connection_string( - connection_string - ) - - # Create the ContainerClient object - container_client = blob_service_client.get_container_client(container) - - # Create the BlobClient object - blob_client = container_client.get_blob_client(path) - except Exception as exc: # pylint: disable=broad-except - log.error("Exception: %s", exc) - return False - - with salt.utils.files.fopen(cached_file_path, "wb") as outfile: - outfile.write(blob_client.download_blob().readall()) - - return diff --git a/salt/states/azurearm_compute.py b/salt/states/azurearm_compute.py deleted file mode 100644 index e23461afd27..00000000000 --- a/salt/states/azurearm_compute.py +++ /dev/null @@ -1,362 +0,0 @@ -""" -Azure (ARM) Compute State Module - -.. versionadded:: 2019.2.0 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -:maintainer: -:maturity: new -:depends: - * `azure `_ >= 2.0.0 - * `azure-common `_ >= 1.1.8 - * `azure-mgmt `_ >= 1.0.0 - * `azure-mgmt-compute `_ >= 1.0.0 - * `azure-mgmt-network `_ >= 1.7.1 - * `azure-mgmt-resource `_ >= 1.1.0 - * `azure-mgmt-storage `_ >= 1.0.0 - * `azure-mgmt-web `_ >= 0.32.0 - * `azure-storage `_ >= 0.34.3 - * `msrestazure `_ >= 0.4.21 -:platform: linux - -:configuration: This module requires Azure Resource Manager credentials to be passed as a dictionary of - keyword arguments to the ``connection_auth`` parameter in order to work properly. Since the authentication - parameters are sensitive, it's recommended to pass them to the states via pillar. - - Required provider parameters: - - if using username and password: - * ``subscription_id`` - * ``username`` - * ``password`` - - if using a service principal: - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - - Optional provider parameters: - - **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. Possible values: - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` - - Example Pillar for Azure Resource Manager authentication: - - .. code-block:: yaml - - azurearm: - user_pass_auth: - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - username: fletch - password: 123pass - mysubscription: - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - tenant: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - client_id: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - secret: XXXXXXXXXXXXXXXXXXXXXXXX - cloud_environment: AZURE_PUBLIC_CLOUD - - Example states using Azure Resource Manager authentication: - - .. code-block:: jinja - - {% set profile = salt['pillar.get']('azurearm:mysubscription') %} - Ensure availability set exists: - azurearm_compute.availability_set_present: - - name: my_avail_set - - resource_group: my_rg - - virtual_machines: - - my_vm1 - - my_vm2 - - tags: - how_awesome: very - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - Ensure availability set is absent: - azurearm_compute.availability_set_absent: - - name: other_avail_set - - resource_group: my_rg - - connection_auth: {{ profile }} - -""" - -# Python libs - -import logging -from functools import wraps - -import salt.utils.azurearm - -__virtualname__ = "azurearm_compute" - -log = logging.getLogger(__name__) - - -def __virtual__(): - """ - Only make this state available if the azurearm_compute module is available. - """ - if "azurearm_compute.availability_set_create_or_update" in __salt__: - return __virtualname__ - return (False, "azurearm module could not be loaded") - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about azurearm deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "The 'azurearm' functionality in Salt has been deprecated and its " - "functionality will be removed in version 3007 in favor of the " - "saltext.azurerm Salt Extension. " - "(https://github.com/salt-extensions/saltext-azurerm)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -@_deprecation_message -def availability_set_present( - name, - resource_group, - tags=None, - platform_update_domain_count=None, - platform_fault_domain_count=None, - virtual_machines=None, - sku=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure an availability set exists. - - :param name: - Name of the availability set. - - :param resource_group: - The resource group assigned to the availability set. - - :param tags: - A dictionary of strings can be passed as tag metadata to the availability set object. - - :param platform_update_domain_count: - An optional parameter which indicates groups of virtual machines and underlying physical hardware that can be - rebooted at the same time. - - :param platform_fault_domain_count: - An optional parameter which defines the group of virtual machines that share a common power source and network - switch. - - :param virtual_machines: - A list of names of existing virtual machines to be included in the availability set. - - :param sku: - The availability set SKU, which specifies whether the availability set is managed or not. Possible values are - 'Aligned' or 'Classic'. An 'Aligned' availability set is managed, 'Classic' is not. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure availability set exists: - azurearm_compute.availability_set_present: - - name: aset1 - - resource_group: group1 - - platform_update_domain_count: 5 - - platform_fault_domain_count: 3 - - sku: aligned - - tags: - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - require: - - azurearm_resource: Ensure resource group exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - if sku: - sku = {"name": sku.capitalize()} - - aset = __salt__["azurearm_compute.availability_set_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" not in aset: - tag_changes = __utils__["dictdiffer.deep_diff"]( - aset.get("tags", {}), tags or {} - ) - if tag_changes: - ret["changes"]["tags"] = tag_changes - - if platform_update_domain_count and ( - int(platform_update_domain_count) - != aset.get("platform_update_domain_count") - ): - ret["changes"]["platform_update_domain_count"] = { - "old": aset.get("platform_update_domain_count"), - "new": platform_update_domain_count, - } - - if platform_fault_domain_count and ( - int(platform_fault_domain_count) != aset.get("platform_fault_domain_count") - ): - ret["changes"]["platform_fault_domain_count"] = { - "old": aset.get("platform_fault_domain_count"), - "new": platform_fault_domain_count, - } - - if sku and (sku["name"] != aset.get("sku", {}).get("name")): - ret["changes"]["sku"] = {"old": aset.get("sku"), "new": sku} - - if virtual_machines: - if not isinstance(virtual_machines, list): - ret["comment"] = "Virtual machines must be supplied as a list!" - return ret - aset_vms = aset.get("virtual_machines", []) - remote_vms = sorted( - vm["id"].split("/")[-1].lower() for vm in aset_vms if "id" in aset_vms - ) - local_vms = sorted(vm.lower() for vm in virtual_machines or []) - if local_vms != remote_vms: - ret["changes"]["virtual_machines"] = { - "old": aset_vms, - "new": virtual_machines, - } - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Availability set {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Availability set {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "virtual_machines": virtual_machines, - "platform_update_domain_count": platform_update_domain_count, - "platform_fault_domain_count": platform_fault_domain_count, - "sku": sku, - "tags": tags, - }, - } - - if __opts__["test"]: - ret["comment"] = "Availability set {} would be created.".format(name) - ret["result"] = None - return ret - - aset_kwargs = kwargs.copy() - aset_kwargs.update(connection_auth) - - aset = __salt__["azurearm_compute.availability_set_create_or_update"]( - name=name, - resource_group=resource_group, - virtual_machines=virtual_machines, - platform_update_domain_count=platform_update_domain_count, - platform_fault_domain_count=platform_fault_domain_count, - sku=sku, - tags=tags, - **aset_kwargs - ) - - if "error" not in aset: - ret["result"] = True - ret["comment"] = "Availability set {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create availability set {}! ({})".format( - name, aset.get("error") - ) - return ret - - -@_deprecation_message -def availability_set_absent(name, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure an availability set does not exist in a resource group. - - :param name: - Name of the availability set. - - :param resource_group: - Name of the resource group containing the availability set. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - aset = __salt__["azurearm_compute.availability_set_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in aset: - ret["result"] = True - ret["comment"] = "Availability set {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Availability set {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": aset, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_compute.availability_set_delete"]( - name, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Availability set {} has been deleted.".format(name) - ret["changes"] = {"old": aset, "new": {}} - return ret - - ret["comment"] = "Failed to delete availability set {}!".format(name) - return ret diff --git a/salt/states/azurearm_dns.py b/salt/states/azurearm_dns.py deleted file mode 100644 index 90f8c0b61c8..00000000000 --- a/salt/states/azurearm_dns.py +++ /dev/null @@ -1,762 +0,0 @@ -""" -Azure (ARM) DNS State Module - -.. versionadded:: 3000 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -:maintainer: -:maturity: new -:depends: - * `azure `_ >= 2.0.0 - * `azure-common `_ >= 1.1.8 - * `azure-mgmt `_ >= 1.0.0 - * `azure-mgmt-compute `_ >= 1.0.0 - * `azure-mgmt-dns `_ >= 1.0.1 - * `azure-mgmt-network `_ >= 1.7.1 - * `azure-mgmt-resource `_ >= 1.1.0 - * `azure-mgmt-storage `_ >= 1.0.0 - * `azure-mgmt-web `_ >= 0.32.0 - * `azure-storage `_ >= 0.34.3 - * `msrestazure `_ >= 0.4.21 - -:platform: linux - -:configuration: - This module requires Azure Resource Manager credentials to be passed as a dictionary of - keyword arguments to the ``connection_auth`` parameter in order to work properly. Since the authentication - parameters are sensitive, it's recommended to pass them to the states via pillar. - -Required provider parameters: - - if using username and password: - - * ``subscription_id`` - * ``username`` - * ``password`` - - if using a service principal: - - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - -Optional provider parameters: - - **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. Possible values: - - Possible values: - - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` - - Example Pillar for Azure Resource Manager authentication: - - .. code-block:: yaml - - azurearm: - user_pass_auth: - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - username: fletch - password: 123pass - mysubscription: - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - tenant: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - client_id: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - secret: XXXXXXXXXXXXXXXXXXXXXXXX - cloud_environment: AZURE_PUBLIC_CLOUD - - Example states using Azure Resource Manager authentication: - - .. code-block:: none - - {% set profile = salt['pillar.get']('azurearm:mysubscription') %} - Ensure DNS zone exists: - azurearm_dns.zone_present: - - name: contoso.com - - resource_group: my_rg - - tags: - how_awesome: very - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - Ensure DNS record set exists: - azurearm_dns.record_set_present: - - name: web - - zone_name: contoso.com - - resource_group: my_rg - - record_type: A - - ttl: 300 - - arecords: - - ipv4_address: 10.0.0.1 - - tags: - how_awesome: very - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - Ensure DNS record set is absent: - azurearm_dns.record_set_absent: - - name: web - - zone_name: contoso.com - - resource_group: my_rg - - record_type: A - - connection_auth: {{ profile }} - - Ensure DNS zone is absent: - azurearm_dns.zone_absent: - - name: contoso.com - - resource_group: my_rg - - connection_auth: {{ profile }} - -""" -import logging -from functools import wraps - -import salt.utils.azurearm - -__virtualname__ = "azurearm_dns" - -log = logging.getLogger(__name__) - - -def __virtual__(): - """ - Only make this state available if the azurearm_dns module is available. - """ - if "azurearm_dns.zones_list_by_resource_group" in __salt__: - return __virtualname__ - return (False, "azurearm_dns module could not be loaded") - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about azurearm deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "The 'azurearm' functionality in Salt has been deprecated and its " - "functionality will be removed in version 3007 in favor of the " - "saltext.azurerm Salt Extension. " - "(https://github.com/salt-extensions/saltext-azurerm)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -@_deprecation_message -def zone_present( - name, - resource_group, - etag=None, - if_match=None, - if_none_match=None, - registration_virtual_networks=None, - resolution_virtual_networks=None, - tags=None, - zone_type="Public", - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 3000 - - Ensure a DNS zone exists. - - :param name: - Name of the DNS zone (without a terminating dot). - - :param resource_group: - The resource group assigned to the DNS zone. - - :param etag: - The etag of the zone. `Etags `_ are used - to handle concurrent changes to the same resource safely. - - :param if_match: - The etag of the DNS zone. Omit this value to always overwrite the current zone. Specify the last-seen etag - value to prevent accidentally overwritting any concurrent changes. - - :param if_none_match: - Set to '*' to allow a new DNS zone to be created, but to prevent updating an existing zone. Other values will - be ignored. - - :param registration_virtual_networks: - A list of references to virtual networks that register hostnames in this DNS zone. This is only when zone_type - is Private. (requires `azure-mgmt-dns `_ >= 2.0.0rc1) - - :param resolution_virtual_networks: - A list of references to virtual networks that resolve records in this DNS zone. This is only when zone_type is - Private. (requires `azure-mgmt-dns `_ >= 2.0.0rc1) - - :param tags: - A dictionary of strings can be passed as tag metadata to the DNS zone object. - - :param zone_type: - The type of this DNS zone (Public or Private). Possible values include: 'Public', 'Private'. Default value: 'Public' - (requires `azure-mgmt-dns `_ >= 2.0.0rc1) - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure DNS zone exists: - azurearm_dns.zone_present: - - name: contoso.com - - resource_group: my_rg - - zone_type: Private - - registration_virtual_networks: - - /subscriptions/{{ sub }}/resourceGroups/my_rg/providers/Microsoft.Network/virtualNetworks/test_vnet - - tags: - how_awesome: very - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - zone = __salt__["azurearm_dns.zone_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" not in zone: - tag_changes = __utils__["dictdiffer.deep_diff"]( - zone.get("tags", {}), tags or {} - ) - if tag_changes: - ret["changes"]["tags"] = tag_changes - - # The zone_type parameter is only accessible in azure-mgmt-dns >=2.0.0rc1 - if zone.get("zone_type"): - if zone.get("zone_type").lower() != zone_type.lower(): - ret["changes"]["zone_type"] = { - "old": zone["zone_type"], - "new": zone_type, - } - - if zone_type.lower() == "private": - # The registration_virtual_networks parameter is only accessible in azure-mgmt-dns >=2.0.0rc1 - if registration_virtual_networks and not isinstance( - registration_virtual_networks, list - ): - ret["comment"] = ( - "registration_virtual_networks must be supplied as a list of" - " VNET ID paths!" - ) - return ret - reg_vnets = zone.get("registration_virtual_networks", []) - remote_reg_vnets = sorted( - vnet["id"].lower() for vnet in reg_vnets if "id" in vnet - ) - local_reg_vnets = sorted( - vnet.lower() for vnet in registration_virtual_networks or [] - ) - if local_reg_vnets != remote_reg_vnets: - ret["changes"]["registration_virtual_networks"] = { - "old": remote_reg_vnets, - "new": local_reg_vnets, - } - - # The resolution_virtual_networks parameter is only accessible in azure-mgmt-dns >=2.0.0rc1 - if resolution_virtual_networks and not isinstance( - resolution_virtual_networks, list - ): - ret["comment"] = ( - "resolution_virtual_networks must be supplied as a list of VNET" - " ID paths!" - ) - return ret - res_vnets = zone.get("resolution_virtual_networks", []) - remote_res_vnets = sorted( - vnet["id"].lower() for vnet in res_vnets if "id" in vnet - ) - local_res_vnets = sorted( - vnet.lower() for vnet in resolution_virtual_networks or [] - ) - if local_res_vnets != remote_res_vnets: - ret["changes"]["resolution_virtual_networks"] = { - "old": remote_res_vnets, - "new": local_res_vnets, - } - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "DNS zone {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "DNS zone {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "resource_group": resource_group, - "etag": etag, - "registration_virtual_networks": registration_virtual_networks, - "resolution_virtual_networks": resolution_virtual_networks, - "tags": tags, - "zone_type": zone_type, - }, - } - - if __opts__["test"]: - ret["comment"] = "DNS zone {} would be created.".format(name) - ret["result"] = None - return ret - - zone_kwargs = kwargs.copy() - zone_kwargs.update(connection_auth) - - zone = __salt__["azurearm_dns.zone_create_or_update"]( - name=name, - resource_group=resource_group, - etag=etag, - if_match=if_match, - if_none_match=if_none_match, - registration_virtual_networks=registration_virtual_networks, - resolution_virtual_networks=resolution_virtual_networks, - tags=tags, - zone_type=zone_type, - **zone_kwargs - ) - - if "error" not in zone: - ret["result"] = True - ret["comment"] = "DNS zone {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create DNS zone {}! ({})".format( - name, zone.get("error") - ) - return ret - - -@_deprecation_message -def zone_absent(name, resource_group, connection_auth=None): - """ - .. versionadded:: 3000 - - Ensure a DNS zone does not exist in the resource group. - - :param name: - Name of the DNS zone. - - :param resource_group: - The resource group assigned to the DNS zone. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - zone = __salt__["azurearm_dns.zone_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in zone: - ret["result"] = True - ret["comment"] = "DNS zone {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "DNS zone {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": zone, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_dns.zone_delete"]( - name, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "DNS zone {} has been deleted.".format(name) - ret["changes"] = {"old": zone, "new": {}} - return ret - - ret["comment"] = "Failed to delete DNS zone {}!".format(name) - return ret - - -@_deprecation_message -def record_set_present( - name, - zone_name, - resource_group, - record_type, - if_match=None, - if_none_match=None, - etag=None, - metadata=None, - ttl=None, - arecords=None, - aaaa_records=None, - mx_records=None, - ns_records=None, - ptr_records=None, - srv_records=None, - txt_records=None, - cname_record=None, - soa_record=None, - caa_records=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 3000 - - Ensure a record set exists in a DNS zone. - - :param name: - The name of the record set, relative to the name of the zone. - - :param zone_name: - Name of the DNS zone (without a terminating dot). - - :param resource_group: - The resource group assigned to the DNS zone. - - :param record_type: - The type of DNS record in this record set. Record sets of type SOA can be updated but not created - (they are created when the DNS zone is created). Possible values include: 'A', 'AAAA', 'CAA', 'CNAME', - 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' - - :param if_match: - The etag of the record set. Omit this value to always overwrite the current record set. Specify the last-seen - etag value to prevent accidentally overwritting any concurrent changes. - - :param if_none_match: - Set to '*' to allow a new record set to be created, but to prevent updating an existing record set. Other values - will be ignored. - - :param etag: - The etag of the record set. `Etags `__ are - used to handle concurrent changes to the same resource safely. - - :param metadata: - A dictionary of strings can be passed as tag metadata to the record set object. - - :param ttl: - The TTL (time-to-live) of the records in the record set. Required when specifying record information. - - :param arecords: - The list of A records in the record set. View the - `Azure SDK documentation `__ - to create a list of dictionaries representing the record objects. - - :param aaaa_records: - The list of AAAA records in the record set. View the - `Azure SDK documentation `__ - to create a list of dictionaries representing the record objects. - - :param mx_records: - The list of MX records in the record set. View the - `Azure SDK documentation `__ - to create a list of dictionaries representing the record objects. - - :param ns_records: - The list of NS records in the record set. View the - `Azure SDK documentation `__ - to create a list of dictionaries representing the record objects. - - :param ptr_records: - The list of PTR records in the record set. View the - `Azure SDK documentation `__ - to create a list of dictionaries representing the record objects. - - :param srv_records: - The list of SRV records in the record set. View the - `Azure SDK documentation `__ - to create a list of dictionaries representing the record objects. - - :param txt_records: - The list of TXT records in the record set. View the - `Azure SDK documentation `__ - to create a list of dictionaries representing the record objects. - - :param cname_record: - The CNAME record in the record set. View the - `Azure SDK documentation `__ - to create a dictionary representing the record object. - - :param soa_record: - The SOA record in the record set. View the - `Azure SDK documentation `__ - to create a dictionary representing the record object. - - :param caa_records: - The list of CAA records in the record set. View the - `Azure SDK documentation `__ - to create a list of dictionaries representing the record objects. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure record set exists: - azurearm_dns.record_set_present: - - name: web - - zone_name: contoso.com - - resource_group: my_rg - - record_type: A - - ttl: 300 - - arecords: - - ipv4_address: 10.0.0.1 - - metadata: - how_awesome: very - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - record_vars = [ - "arecords", - "aaaa_records", - "mx_records", - "ns_records", - "ptr_records", - "srv_records", - "txt_records", - "cname_record", - "soa_record", - "caa_records", - ] - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - rec_set = __salt__["azurearm_dns.record_set_get"]( - name, - zone_name, - resource_group, - record_type, - azurearm_log_level="info", - **connection_auth - ) - - if "error" not in rec_set: - metadata_changes = __utils__["dictdiffer.deep_diff"]( - rec_set.get("metadata", {}), metadata or {} - ) - if metadata_changes: - ret["changes"]["metadata"] = metadata_changes - - for record_str in record_vars: - # pylint: disable=eval-used - record = eval(record_str) - if record: - if not ttl: - ret[ - "comment" - ] = "TTL is required when specifying record information!" - return ret - if not rec_set.get(record_str): - ret["changes"] = {"new": {record_str: record}} - continue - if record_str[-1] != "s": - if not isinstance(record, dict): - ret[ - "comment" - ] = "{} record information must be specified as a dictionary!".format( - record_str - ) - return ret - for k, v in record.items(): - if v != rec_set[record_str].get(k): - ret["changes"] = {"new": {record_str: record}} - elif record_str[-1] == "s": - if not isinstance(record, list): - ret["comment"] = ( - "{} record information must be specified as a list of" - " dictionaries!".format(record_str) - ) - return ret - local, remote = ( - sorted(config) for config in (record, rec_set[record_str]) - ) - for val in local: - for key in val: - local_val = val[key] - remote_val = remote.get(key) - if isinstance(local_val, str): - local_val = local_val.lower() - if isinstance(remote_val, str): - remote_val = remote_val.lower() - if local_val != remote_val: - ret["changes"] = {"new": {record_str: record}} - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Record set {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Record set {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "zone_name": zone_name, - "resource_group": resource_group, - "record_type": record_type, - "etag": etag, - "metadata": metadata, - "ttl": ttl, - }, - } - for record in record_vars: - # pylint: disable=eval-used - if eval(record): - # pylint: disable=eval-used - ret["changes"]["new"][record] = eval(record) - - if __opts__["test"]: - ret["comment"] = "Record set {} would be created.".format(name) - ret["result"] = None - return ret - - rec_set_kwargs = kwargs.copy() - rec_set_kwargs.update(connection_auth) - - rec_set = __salt__["azurearm_dns.record_set_create_or_update"]( - name=name, - zone_name=zone_name, - resource_group=resource_group, - record_type=record_type, - if_match=if_match, - if_none_match=if_none_match, - etag=etag, - ttl=ttl, - metadata=metadata, - arecords=arecords, - aaaa_records=aaaa_records, - mx_records=mx_records, - ns_records=ns_records, - ptr_records=ptr_records, - srv_records=srv_records, - txt_records=txt_records, - cname_record=cname_record, - soa_record=soa_record, - caa_records=caa_records, - **rec_set_kwargs - ) - - if "error" not in rec_set: - ret["result"] = True - ret["comment"] = "Record set {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create record set {}! ({})".format( - name, rec_set.get("error") - ) - return ret - - -@_deprecation_message -def record_set_absent(name, zone_name, resource_group, connection_auth=None): - """ - .. versionadded:: 3000 - - Ensure a record set does not exist in the DNS zone. - - :param name: - Name of the record set. - - :param zone_name: - Name of the DNS zone. - - :param resource_group: - The resource group assigned to the DNS zone. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - rec_set = __salt__["azurearm_dns.record_set_get"]( - name, zone_name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in rec_set: - ret["result"] = True - ret["comment"] = "Record set {} was not found in zone {}.".format( - name, zone_name - ) - return ret - - elif __opts__["test"]: - ret["comment"] = "Record set {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": rec_set, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_dns.record_set_delete"]( - name, zone_name, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Record set {} has been deleted.".format(name) - ret["changes"] = {"old": rec_set, "new": {}} - return ret - - ret["comment"] = "Failed to delete record set {}!".format(name) - return ret diff --git a/salt/states/azurearm_network.py b/salt/states/azurearm_network.py deleted file mode 100644 index 2555a2d06ad..00000000000 --- a/salt/states/azurearm_network.py +++ /dev/null @@ -1,2594 +0,0 @@ -""" -Azure (ARM) Network State Module - -.. versionadded:: 2019.2.0 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -:maintainer: -:maturity: new -:depends: - * `azure `_ >= 2.0.0 - * `azure-common `_ >= 1.1.8 - * `azure-mgmt `_ >= 1.0.0 - * `azure-mgmt-compute `_ >= 1.0.0 - * `azure-mgmt-network `_ >= 1.7.1 - * `azure-mgmt-resource `_ >= 1.1.0 - * `azure-mgmt-storage `_ >= 1.0.0 - * `azure-mgmt-web `_ >= 0.32.0 - * `azure-storage `_ >= 0.34.3 - * `msrestazure `_ >= 0.4.21 -:platform: linux - -:configuration: This module requires Azure Resource Manager credentials to be passed as a dictionary of - keyword arguments to the ``connection_auth`` parameter in order to work properly. Since the authentication - parameters are sensitive, it's recommended to pass them to the states via pillar. - - Required provider parameters: - - if using username and password: - * ``subscription_id`` - * ``username`` - * ``password`` - - if using a service principal: - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - - Optional provider parameters: - - **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. Possible values: - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` - - Example Pillar for Azure Resource Manager authentication: - - .. code-block:: yaml - - azurearm: - user_pass_auth: - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - username: fletch - password: 123pass - mysubscription: - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - tenant: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - client_id: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - secret: XXXXXXXXXXXXXXXXXXXXXXXX - cloud_environment: AZURE_PUBLIC_CLOUD - - Example states using Azure Resource Manager authentication: - - .. code-block:: jinja - - {% set profile = salt['pillar.get']('azurearm:mysubscription') %} - Ensure virtual network exists: - azurearm_network.virtual_network_present: - - name: my_vnet - - resource_group: my_rg - - address_prefixes: - - '10.0.0.0/8' - - '192.168.0.0/16' - - dns_servers: - - '8.8.8.8' - - tags: - how_awesome: very - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - Ensure virtual network is absent: - azurearm_network.virtual_network_absent: - - name: other_vnet - - resource_group: my_rg - - connection_auth: {{ profile }} - -""" -import logging -from functools import wraps - -import salt.utils.azurearm - -__virtualname__ = "azurearm_network" - -log = logging.getLogger(__name__) - - -def __virtual__(): - """ - Only make this state available if the azurearm_network module is available. - """ - if "azurearm_network.check_ip_address_availability" in __salt__: - return __virtualname__ - return (False, "azurearm_network module could not be loaded") - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about azurearm deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "The 'azurearm' functionality in Salt has been deprecated and its " - "functionality will be removed in version 3007 in favor of the " - "saltext.azurerm Salt Extension. " - "(https://github.com/salt-extensions/saltext-azurerm)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -@_deprecation_message -def virtual_network_present( - name, - address_prefixes, - resource_group, - dns_servers=None, - tags=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a virtual network exists. - - :param name: - Name of the virtual network. - - :param resource_group: - The resource group assigned to the virtual network. - - :param address_prefixes: - A list of CIDR blocks which can be used by subnets within the virtual network. - - :param dns_servers: - A list of DNS server addresses. - - :param tags: - A dictionary of strings can be passed as tag metadata to the virtual network object. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure virtual network exists: - azurearm_network.virtual_network_present: - - name: vnet1 - - resource_group: group1 - - address_prefixes: - - '10.0.0.0/8' - - '192.168.0.0/16' - - dns_servers: - - '8.8.8.8' - - tags: - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - require: - - azurearm_resource: Ensure resource group exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - vnet = __salt__["azurearm_network.virtual_network_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" not in vnet: - tag_changes = __utils__["dictdiffer.deep_diff"]( - vnet.get("tags", {}), tags or {} - ) - if tag_changes: - ret["changes"]["tags"] = tag_changes - - dns_changes = set(dns_servers or []).symmetric_difference( - set(vnet.get("dhcp_options", {}).get("dns_servers", [])) - ) - if dns_changes: - ret["changes"]["dns_servers"] = { - "old": vnet.get("dhcp_options", {}).get("dns_servers", []), - "new": dns_servers, - } - - addr_changes = set(address_prefixes or []).symmetric_difference( - set(vnet.get("address_space", {}).get("address_prefixes", [])) - ) - if addr_changes: - ret["changes"]["address_space"] = { - "address_prefixes": { - "old": vnet.get("address_space", {}).get("address_prefixes", []), - "new": address_prefixes, - } - } - - if kwargs.get("enable_ddos_protection", False) != vnet.get( - "enable_ddos_protection" - ): - ret["changes"]["enable_ddos_protection"] = { - "old": vnet.get("enable_ddos_protection"), - "new": kwargs.get("enable_ddos_protection"), - } - - if kwargs.get("enable_vm_protection", False) != vnet.get( - "enable_vm_protection" - ): - ret["changes"]["enable_vm_protection"] = { - "old": vnet.get("enable_vm_protection"), - "new": kwargs.get("enable_vm_protection"), - } - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Virtual network {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Virtual network {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "resource_group": resource_group, - "address_space": {"address_prefixes": address_prefixes}, - "dhcp_options": {"dns_servers": dns_servers}, - "enable_ddos_protection": kwargs.get("enable_ddos_protection", False), - "enable_vm_protection": kwargs.get("enable_vm_protection", False), - "tags": tags, - }, - } - - if __opts__["test"]: - ret["comment"] = "Virtual network {} would be created.".format(name) - ret["result"] = None - return ret - - vnet_kwargs = kwargs.copy() - vnet_kwargs.update(connection_auth) - - vnet = __salt__["azurearm_network.virtual_network_create_or_update"]( - name=name, - resource_group=resource_group, - address_prefixes=address_prefixes, - dns_servers=dns_servers, - tags=tags, - **vnet_kwargs - ) - - if "error" not in vnet: - ret["result"] = True - ret["comment"] = "Virtual network {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create virtual network {}! ({})".format( - name, vnet.get("error") - ) - return ret - - -@_deprecation_message -def virtual_network_absent(name, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a virtual network does not exist in the resource group. - - :param name: - Name of the virtual network. - - :param resource_group: - The resource group assigned to the virtual network. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - vnet = __salt__["azurearm_network.virtual_network_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in vnet: - ret["result"] = True - ret["comment"] = "Virtual network {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Virtual network {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": vnet, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_network.virtual_network_delete"]( - name, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Virtual network {} has been deleted.".format(name) - ret["changes"] = {"old": vnet, "new": {}} - return ret - - ret["comment"] = "Failed to delete virtual network {}!".format(name) - return ret - - -@_deprecation_message -def subnet_present( - name, - address_prefix, - virtual_network, - resource_group, - security_group=None, - route_table=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a subnet exists. - - :param name: - Name of the subnet. - - :param address_prefix: - A CIDR block used by the subnet within the virtual network. - - :param virtual_network: - Name of the existing virtual network to contain the subnet. - - :param resource_group: - The resource group assigned to the virtual network. - - :param security_group: - The name of the existing network security group to assign to the subnet. - - :param route_table: - The name of the existing route table to assign to the subnet. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure subnet exists: - azurearm_network.subnet_present: - - name: vnet1_sn1 - - virtual_network: vnet1 - - resource_group: group1 - - address_prefix: '192.168.1.0/24' - - security_group: nsg1 - - route_table: rt1 - - connection_auth: {{ profile }} - - require: - - azurearm_network: Ensure virtual network exists - - azurearm_network: Ensure network security group exists - - azurearm_network: Ensure route table exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - snet = __salt__["azurearm_network.subnet_get"]( - name, - virtual_network, - resource_group, - azurearm_log_level="info", - **connection_auth - ) - - if "error" not in snet: - if address_prefix != snet.get("address_prefix"): - ret["changes"]["address_prefix"] = { - "old": snet.get("address_prefix"), - "new": address_prefix, - } - - nsg_name = None - if snet.get("network_security_group"): - nsg_name = snet["network_security_group"]["id"].split("/")[-1] - - if security_group and (security_group != nsg_name): - ret["changes"]["network_security_group"] = { - "old": nsg_name, - "new": security_group, - } - - rttbl_name = None - if snet.get("route_table"): - rttbl_name = snet["route_table"]["id"].split("/")[-1] - - if route_table and (route_table != rttbl_name): - ret["changes"]["route_table"] = {"old": rttbl_name, "new": route_table} - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Subnet {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Subnet {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "address_prefix": address_prefix, - "network_security_group": security_group, - "route_table": route_table, - }, - } - - if __opts__["test"]: - ret["comment"] = "Subnet {} would be created.".format(name) - ret["result"] = None - return ret - - snet_kwargs = kwargs.copy() - snet_kwargs.update(connection_auth) - - snet = __salt__["azurearm_network.subnet_create_or_update"]( - name=name, - virtual_network=virtual_network, - resource_group=resource_group, - address_prefix=address_prefix, - network_security_group=security_group, - route_table=route_table, - **snet_kwargs - ) - - if "error" not in snet: - ret["result"] = True - ret["comment"] = "Subnet {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create subnet {}! ({})".format(name, snet.get("error")) - return ret - - -@_deprecation_message -def subnet_absent(name, virtual_network, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a virtual network does not exist in the virtual network. - - :param name: - Name of the subnet. - - :param virtual_network: - Name of the existing virtual network containing the subnet. - - :param resource_group: - The resource group assigned to the virtual network. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - snet = __salt__["azurearm_network.subnet_get"]( - name, - virtual_network, - resource_group, - azurearm_log_level="info", - **connection_auth - ) - - if "error" in snet: - ret["result"] = True - ret["comment"] = "Subnet {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Subnet {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": snet, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_network.subnet_delete"]( - name, virtual_network, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Subnet {} has been deleted.".format(name) - ret["changes"] = {"old": snet, "new": {}} - return ret - - ret["comment"] = "Failed to delete subnet {}!".format(name) - return ret - - -@_deprecation_message -def network_security_group_present( - name, resource_group, tags=None, security_rules=None, connection_auth=None, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a network security group exists. - - :param name: - Name of the network security group. - - :param resource_group: - The resource group assigned to the network security group. - - :param tags: - A dictionary of strings can be passed as tag metadata to the network security group object. - - :param security_rules: An optional list of dictionaries representing valid SecurityRule objects. See the - documentation for the security_rule_present state or security_rule_create_or_update execution module - for more information on required and optional parameters for security rules. The rules are only - managed if this parameter is present. When this parameter is absent, implemented rules will not be removed, - and will merely become unmanaged. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure network security group exists: - azurearm_network.network_security_group_present: - - name: nsg1 - - resource_group: group1 - - security_rules: - - name: nsg1_rule1 - priority: 100 - protocol: tcp - access: allow - direction: outbound - source_address_prefix: virtualnetwork - destination_address_prefix: internet - source_port_range: '*' - destination_port_range: '*' - - name: nsg1_rule2 - priority: 101 - protocol: tcp - access: allow - direction: inbound - source_address_prefix: internet - destination_address_prefix: virtualnetwork - source_port_range: '*' - destination_port_ranges: - - '80' - - '443' - - tags: - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - require: - - azurearm_resource: Ensure resource group exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - nsg = __salt__["azurearm_network.network_security_group_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" not in nsg: - tag_changes = __utils__["dictdiffer.deep_diff"](nsg.get("tags", {}), tags or {}) - if tag_changes: - ret["changes"]["tags"] = tag_changes - - if security_rules: - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - nsg.get("security_rules", []), security_rules - ) - - if comp_ret.get("comment"): - ret["comment"] = '"security_rules" {}'.format(comp_ret["comment"]) - return ret - - if comp_ret.get("changes"): - ret["changes"]["security_rules"] = comp_ret["changes"] - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Network security group {} is already present.".format( - name - ) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Network security group {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "resource_group": resource_group, - "tags": tags, - "security_rules": security_rules, - }, - } - - if __opts__["test"]: - ret["comment"] = "Network security group {} would be created.".format(name) - ret["result"] = None - return ret - - nsg_kwargs = kwargs.copy() - nsg_kwargs.update(connection_auth) - - nsg = __salt__["azurearm_network.network_security_group_create_or_update"]( - name=name, - resource_group=resource_group, - tags=tags, - security_rules=security_rules, - **nsg_kwargs - ) - - if "error" not in nsg: - ret["result"] = True - ret["comment"] = "Network security group {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create network security group {}! ({})".format( - name, nsg.get("error") - ) - return ret - - -@_deprecation_message -def network_security_group_absent(name, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a network security group does not exist in the resource group. - - :param name: - Name of the network security group. - - :param resource_group: - The resource group assigned to the network security group. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - nsg = __salt__["azurearm_network.network_security_group_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in nsg: - ret["result"] = True - ret["comment"] = "Network security group {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Network security group {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": nsg, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_network.network_security_group_delete"]( - name, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Network security group {} has been deleted.".format(name) - ret["changes"] = {"old": nsg, "new": {}} - return ret - - ret["comment"] = "Failed to delete network security group {}!".format(name) - return ret - - -@_deprecation_message -def security_rule_present( - name, - access, - direction, - priority, - protocol, - security_group, - resource_group, - destination_address_prefix=None, - destination_port_range=None, - source_address_prefix=None, - source_port_range=None, - description=None, - destination_address_prefixes=None, - destination_port_ranges=None, - source_address_prefixes=None, - source_port_ranges=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a security rule exists. - - :param name: - Name of the security rule. - - :param access: - 'allow' or 'deny' - - :param direction: - 'inbound' or 'outbound' - - :param priority: - Integer between 100 and 4096 used for ordering rule application. - - :param protocol: - 'tcp', 'udp', or '*' - - :param security_group: - The name of the existing network security group to contain the security rule. - - :param resource_group: - The resource group assigned to the network security group. - - :param description: - Optional description of the security rule. - - :param destination_address_prefix: - The CIDR or destination IP range. Asterix '*' can also be used to match all destination IPs. - Default tags such as 'VirtualNetwork', 'AzureLoadBalancer' and 'Internet' can also be used. - If this is an ingress rule, specifies where network traffic originates from. - - :param destination_port_range: - The destination port or range. Integer or range between 0 and 65535. Asterix '*' - can also be used to match all ports. - - :param source_address_prefix: - The CIDR or source IP range. Asterix '*' can also be used to match all source IPs. - Default tags such as 'VirtualNetwork', 'AzureLoadBalancer' and 'Internet' can also be used. - If this is an ingress rule, specifies where network traffic originates from. - - :param source_port_range: - The source port or range. Integer or range between 0 and 65535. Asterix '*' - can also be used to match all ports. - - :param destination_address_prefixes: - A list of destination_address_prefix values. This parameter overrides destination_address_prefix - and will cause any value entered there to be ignored. - - :param destination_port_ranges: - A list of destination_port_range values. This parameter overrides destination_port_range - and will cause any value entered there to be ignored. - - :param source_address_prefixes: - A list of source_address_prefix values. This parameter overrides source_address_prefix - and will cause any value entered there to be ignored. - - :param source_port_ranges: - A list of source_port_range values. This parameter overrides source_port_range - and will cause any value entered there to be ignored. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure security rule exists: - azurearm_network.security_rule_present: - - name: nsg1_rule2 - - security_group: nsg1 - - resource_group: group1 - - priority: 101 - - protocol: tcp - - access: allow - - direction: inbound - - source_address_prefix: internet - - destination_address_prefix: virtualnetwork - - source_port_range: '*' - - destination_port_ranges: - - '80' - - '443' - - connection_auth: {{ profile }} - - require: - - azurearm_network: Ensure network security group exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - exclusive_params = [ - ("source_port_ranges", "source_port_range"), - ("source_address_prefixes", "source_address_prefix"), - ("destination_port_ranges", "destination_port_range"), - ("destination_address_prefixes", "destination_address_prefix"), - ] - - for params in exclusive_params: - # pylint: disable=eval-used - if not eval(params[0]) and not eval(params[1]): - ret["comment"] = "Either the {} or {} parameter must be provided!".format( - params[0], params[1] - ) - return ret - # pylint: disable=eval-used - if eval(params[0]): - # pylint: disable=eval-used - if not isinstance(eval(params[0]), list): - ret["comment"] = "The {} parameter must be a list!".format(params[0]) - return ret - # pylint: disable=exec-used - exec("{} = None".format(params[1])) - - rule = __salt__["azurearm_network.security_rule_get"]( - name, - security_group, - resource_group, - azurearm_log_level="info", - **connection_auth - ) - - if "error" not in rule: - # access changes - if access.capitalize() != rule.get("access"): - ret["changes"]["access"] = {"old": rule.get("access"), "new": access} - - # description changes - if description != rule.get("description"): - ret["changes"]["description"] = { - "old": rule.get("description"), - "new": description, - } - - # direction changes - if direction.capitalize() != rule.get("direction"): - ret["changes"]["direction"] = { - "old": rule.get("direction"), - "new": direction, - } - - # priority changes - if int(priority) != rule.get("priority"): - ret["changes"]["priority"] = {"old": rule.get("priority"), "new": priority} - - # protocol changes - if protocol.lower() != rule.get("protocol", "").lower(): - ret["changes"]["protocol"] = {"old": rule.get("protocol"), "new": protocol} - - # destination_port_range changes - if destination_port_range != rule.get("destination_port_range"): - ret["changes"]["destination_port_range"] = { - "old": rule.get("destination_port_range"), - "new": destination_port_range, - } - - # source_port_range changes - if source_port_range != rule.get("source_port_range"): - ret["changes"]["source_port_range"] = { - "old": rule.get("source_port_range"), - "new": source_port_range, - } - - # destination_port_ranges changes - if sorted(destination_port_ranges or []) != sorted( - rule.get("destination_port_ranges", []) - ): - ret["changes"]["destination_port_ranges"] = { - "old": rule.get("destination_port_ranges"), - "new": destination_port_ranges, - } - - # source_port_ranges changes - if sorted(source_port_ranges or []) != sorted( - rule.get("source_port_ranges", []) - ): - ret["changes"]["source_port_ranges"] = { - "old": rule.get("source_port_ranges"), - "new": source_port_ranges, - } - - # destination_address_prefix changes - if (destination_address_prefix or "").lower() != rule.get( - "destination_address_prefix", "" - ).lower(): - ret["changes"]["destination_address_prefix"] = { - "old": rule.get("destination_address_prefix"), - "new": destination_address_prefix, - } - - # source_address_prefix changes - if (source_address_prefix or "").lower() != rule.get( - "source_address_prefix", "" - ).lower(): - ret["changes"]["source_address_prefix"] = { - "old": rule.get("source_address_prefix"), - "new": source_address_prefix, - } - - # destination_address_prefixes changes - if sorted(destination_address_prefixes or []) != sorted( - rule.get("destination_address_prefixes", []) - ): - if len(destination_address_prefixes or []) != len( - rule.get("destination_address_prefixes", []) - ): - ret["changes"]["destination_address_prefixes"] = { - "old": rule.get("destination_address_prefixes"), - "new": destination_address_prefixes, - } - else: - local_dst_addrs, remote_dst_addrs = ( - sorted(destination_address_prefixes), - sorted(rule.get("destination_address_prefixes")), - ) - for idx, val in enumerate(local_dst_addrs): - if val.lower() != remote_dst_addrs[idx].lower(): - ret["changes"]["destination_address_prefixes"] = { - "old": rule.get("destination_address_prefixes"), - "new": destination_address_prefixes, - } - break - - # source_address_prefixes changes - if sorted(source_address_prefixes or []) != sorted( - rule.get("source_address_prefixes", []) - ): - if len(source_address_prefixes or []) != len( - rule.get("source_address_prefixes", []) - ): - ret["changes"]["source_address_prefixes"] = { - "old": rule.get("source_address_prefixes"), - "new": source_address_prefixes, - } - else: - local_src_addrs, remote_src_addrs = ( - sorted(source_address_prefixes), - sorted(rule.get("source_address_prefixes")), - ) - for idx, val in enumerate(local_src_addrs): - if val.lower() != remote_src_addrs[idx].lower(): - ret["changes"]["source_address_prefixes"] = { - "old": rule.get("source_address_prefixes"), - "new": source_address_prefixes, - } - break - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Security rule {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Security rule {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "access": access, - "description": description, - "direction": direction, - "priority": priority, - "protocol": protocol, - "destination_address_prefix": destination_address_prefix, - "destination_address_prefixes": destination_address_prefixes, - "destination_port_range": destination_port_range, - "destination_port_ranges": destination_port_ranges, - "source_address_prefix": source_address_prefix, - "source_address_prefixes": source_address_prefixes, - "source_port_range": source_port_range, - "source_port_ranges": source_port_ranges, - }, - } - - if __opts__["test"]: - ret["comment"] = "Security rule {} would be created.".format(name) - ret["result"] = None - return ret - - rule_kwargs = kwargs.copy() - rule_kwargs.update(connection_auth) - - rule = __salt__["azurearm_network.security_rule_create_or_update"]( - name=name, - access=access, - description=description, - direction=direction, - priority=priority, - protocol=protocol, - security_group=security_group, - resource_group=resource_group, - destination_address_prefix=destination_address_prefix, - destination_address_prefixes=destination_address_prefixes, - destination_port_range=destination_port_range, - destination_port_ranges=destination_port_ranges, - source_address_prefix=source_address_prefix, - source_address_prefixes=source_address_prefixes, - source_port_range=source_port_range, - source_port_ranges=source_port_ranges, - **rule_kwargs - ) - - if "error" not in rule: - ret["result"] = True - ret["comment"] = "Security rule {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create security rule {}! ({})".format( - name, rule.get("error") - ) - return ret - - -@_deprecation_message -def security_rule_absent(name, security_group, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a security rule does not exist in the network security group. - - :param name: - Name of the security rule. - - :param security_group: - The network security group containing the security rule. - - :param resource_group: - The resource group assigned to the network security group. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - rule = __salt__["azurearm_network.security_rule_get"]( - name, - security_group, - resource_group, - azurearm_log_level="info", - **connection_auth - ) - - if "error" in rule: - ret["result"] = True - ret["comment"] = "Security rule {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Security rule {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": rule, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_network.security_rule_delete"]( - name, security_group, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Security rule {} has been deleted.".format(name) - ret["changes"] = {"old": rule, "new": {}} - return ret - - ret["comment"] = "Failed to delete security rule {}!".format(name) - return ret - - -@_deprecation_message -def load_balancer_present( - name, - resource_group, - sku=None, - frontend_ip_configurations=None, - backend_address_pools=None, - load_balancing_rules=None, - probes=None, - inbound_nat_rules=None, - inbound_nat_pools=None, - outbound_nat_rules=None, - tags=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a load balancer exists. - - :param name: - Name of the load balancer. - - :param resource_group: - The resource group assigned to the load balancer. - - :param sku: - The load balancer SKU, which can be 'Basic' or 'Standard'. - - :param tags: - A dictionary of strings can be passed as tag metadata to the load balancer object. - - :param frontend_ip_configurations: - An optional list of dictionaries representing valid FrontendIPConfiguration objects. A frontend IP - configuration can be either private (using private IP address and subnet parameters) or public (using a - reference to a public IP address object). Valid parameters are: - - - ``name``: The name of the resource that is unique within a resource group. - - ``private_ip_address``: The private IP address of the IP configuration. Required if - 'private_ip_allocation_method' is 'Static'. - - ``private_ip_allocation_method``: The Private IP allocation method. Possible values are: 'Static' and - 'Dynamic'. - - ``subnet``: Name of an existing subnet inside of which the frontend IP will reside. - - ``public_ip_address``: Name of an existing public IP address which will be assigned to the frontend IP object. - - :param backend_address_pools: - An optional list of dictionaries representing valid BackendAddressPool objects. Only the 'name' parameter is - valid for a BackendAddressPool dictionary. All other parameters are read-only references from other objects - linking to the backend address pool. Inbound traffic is randomly load balanced across IPs in the backend IPs. - - :param probes: - An optional list of dictionaries representing valid Probe objects. Valid parameters are: - - - ``name``: The name of the resource that is unique within a resource group. - - ``protocol``: The protocol of the endpoint. Possible values are 'Http' or 'Tcp'. If 'Tcp' is specified, a - received ACK is required for the probe to be successful. If 'Http' is specified, a 200 OK response from the - specified URI is required for the probe to be successful. - - ``port``: The port for communicating the probe. Possible values range from 1 to 65535, inclusive. - - ``interval_in_seconds``: The interval, in seconds, for how frequently to probe the endpoint for health status. - Typically, the interval is slightly less than half the allocated timeout period (in seconds) which allows two - full probes before taking the instance out of rotation. The default value is 15, the minimum value is 5. - - ``number_of_probes``: The number of probes where if no response, will result in stopping further traffic from - being delivered to the endpoint. This values allows endpoints to be taken out of rotation faster or slower - than the typical times used in Azure. - - ``request_path``: The URI used for requesting health status from the VM. Path is required if a protocol is - set to 'Http'. Otherwise, it is not allowed. There is no default value. - - :param load_balancing_rules: - An optional list of dictionaries representing valid LoadBalancingRule objects. Valid parameters are: - - - ``name``: The name of the resource that is unique within a resource group. - - ``load_distribution``: The load distribution policy for this rule. Possible values are 'Default', 'SourceIP', - and 'SourceIPProtocol'. - - ``frontend_port``: The port for the external endpoint. Port numbers for each rule must be unique within the - Load Balancer. Acceptable values are between 0 and 65534. Note that value 0 enables 'Any Port'. - - ``backend_port``: The port used for internal connections on the endpoint. Acceptable values are between 0 and - 65535. Note that value 0 enables 'Any Port'. - - ``idle_timeout_in_minutes``: The timeout for the TCP idle connection. The value can be set between 4 and 30 - minutes. The default value is 4 minutes. This element is only used when the protocol is set to TCP. - - ``enable_floating_ip``: Configures a virtual machine's endpoint for the floating IP capability required - to configure a SQL AlwaysOn Availability Group. This setting is required when using the SQL AlwaysOn - Availability Groups in SQL server. This setting can't be changed after you create the endpoint. - - ``disable_outbound_snat``: Configures SNAT for the VMs in the backend pool to use the public IP address - specified in the frontend of the load balancing rule. - - ``frontend_ip_configuration``: Name of the frontend IP configuration object used by the load balancing rule - object. - - ``backend_address_pool``: Name of the backend address pool object used by the load balancing rule object. - Inbound traffic is randomly load balanced across IPs in the backend IPs. - - ``probe``: Name of the probe object used by the load balancing rule object. - - :param inbound_nat_rules: - An optional list of dictionaries representing valid InboundNatRule objects. Defining inbound NAT rules on your - load balancer is mutually exclusive with defining an inbound NAT pool. Inbound NAT pools are referenced from - virtual machine scale sets. NICs that are associated with individual virtual machines cannot reference an - Inbound NAT pool. They have to reference individual inbound NAT rules. Valid parameters are: - - - ``name``: The name of the resource that is unique within a resource group. - - ``frontend_ip_configuration``: Name of the frontend IP configuration object used by the inbound NAT rule - object. - - ``protocol``: Possible values include 'Udp', 'Tcp', or 'All'. - - ``frontend_port``: The port for the external endpoint. Port numbers for each rule must be unique within the - Load Balancer. Acceptable values range from 1 to 65534. - - ``backend_port``: The port used for the internal endpoint. Acceptable values range from 1 to 65535. - - ``idle_timeout_in_minutes``: The timeout for the TCP idle connection. The value can be set between 4 and 30 - minutes. The default value is 4 minutes. This element is only used when the protocol is set to TCP. - - ``enable_floating_ip``: Configures a virtual machine's endpoint for the floating IP capability required - to configure a SQL AlwaysOn Availability Group. This setting is required when using the SQL AlwaysOn - Availability Groups in SQL server. This setting can't be changed after you create the endpoint. - - :param inbound_nat_pools: - An optional list of dictionaries representing valid InboundNatPool objects. They define an external port range - for inbound NAT to a single backend port on NICs associated with a load balancer. Inbound NAT rules are created - automatically for each NIC associated with the Load Balancer using an external port from this range. Defining an - Inbound NAT pool on your Load Balancer is mutually exclusive with defining inbound NAT rules. Inbound NAT pools - are referenced from virtual machine scale sets. NICs that are associated with individual virtual machines cannot - reference an inbound NAT pool. They have to reference individual inbound NAT rules. Valid parameters are: - - - ``name``: The name of the resource that is unique within a resource group. - - ``frontend_ip_configuration``: Name of the frontend IP configuration object used by the inbound NAT pool - object. - - ``protocol``: Possible values include 'Udp', 'Tcp', or 'All'. - - ``frontend_port_range_start``: The first port number in the range of external ports that will be used to - provide Inbound NAT to NICs associated with a load balancer. Acceptable values range between 1 and 65534. - - ``frontend_port_range_end``: The last port number in the range of external ports that will be used to - provide Inbound NAT to NICs associated with a load balancer. Acceptable values range between 1 and 65535. - - ``backend_port``: The port used for internal connections to the endpoint. Acceptable values are between 1 and - 65535. - - :param outbound_nat_rules: - An optional list of dictionaries representing valid OutboundNatRule objects. Valid parameters are: - - - ``name``: The name of the resource that is unique within a resource group. - - ``frontend_ip_configuration``: Name of the frontend IP configuration object used by the outbound NAT rule - object. - - ``backend_address_pool``: Name of the backend address pool object used by the outbound NAT rule object. - Outbound traffic is randomly load balanced across IPs in the backend IPs. - - ``allocated_outbound_ports``: The number of outbound ports to be used for NAT. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure load balancer exists: - azurearm_network.load_balancer_present: - - name: lb1 - - resource_group: group1 - - location: eastus - - frontend_ip_configurations: - - name: lb1_feip1 - public_ip_address: pub_ip1 - - backend_address_pools: - - name: lb1_bepool1 - - probes: - - name: lb1_webprobe1 - protocol: tcp - port: 80 - interval_in_seconds: 5 - number_of_probes: 2 - - load_balancing_rules: - - name: lb1_webprobe1 - protocol: tcp - frontend_port: 80 - backend_port: 80 - idle_timeout_in_minutes: 4 - frontend_ip_configuration: lb1_feip1 - backend_address_pool: lb1_bepool1 - probe: lb1_webprobe1 - - tags: - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - require: - - azurearm_resource: Ensure resource group exists - - azurearm_network: Ensure public IP exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - if sku: - sku = {"name": sku.capitalize()} - - load_bal = __salt__["azurearm_network.load_balancer_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" not in load_bal: - # tag changes - tag_changes = __utils__["dictdiffer.deep_diff"]( - load_bal.get("tags", {}), tags or {} - ) - if tag_changes: - ret["changes"]["tags"] = tag_changes - - # sku changes - if sku: - sku_changes = __utils__["dictdiffer.deep_diff"]( - load_bal.get("sku", {}), sku - ) - if sku_changes: - ret["changes"]["sku"] = sku_changes - - # frontend_ip_configurations changes - if frontend_ip_configurations: - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - load_bal.get("frontend_ip_configurations", []), - frontend_ip_configurations, - ["public_ip_address", "subnet"], - ) - - if comp_ret.get("comment"): - ret["comment"] = '"frontend_ip_configurations" {}'.format( - comp_ret["comment"] - ) - return ret - - if comp_ret.get("changes"): - ret["changes"]["frontend_ip_configurations"] = comp_ret["changes"] - - # backend_address_pools changes - if backend_address_pools: - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - load_bal.get("backend_address_pools", []), backend_address_pools - ) - - if comp_ret.get("comment"): - ret["comment"] = '"backend_address_pools" {}'.format( - comp_ret["comment"] - ) - return ret - - if comp_ret.get("changes"): - ret["changes"]["backend_address_pools"] = comp_ret["changes"] - - # probes changes - if probes: - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - load_bal.get("probes", []), probes - ) - - if comp_ret.get("comment"): - ret["comment"] = '"probes" {}'.format(comp_ret["comment"]) - return ret - - if comp_ret.get("changes"): - ret["changes"]["probes"] = comp_ret["changes"] - - # load_balancing_rules changes - if load_balancing_rules: - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - load_bal.get("load_balancing_rules", []), - load_balancing_rules, - ["frontend_ip_configuration", "backend_address_pool", "probe"], - ) - - if comp_ret.get("comment"): - ret["comment"] = '"load_balancing_rules" {}'.format(comp_ret["comment"]) - return ret - - if comp_ret.get("changes"): - ret["changes"]["load_balancing_rules"] = comp_ret["changes"] - - # inbound_nat_rules changes - if inbound_nat_rules: - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - load_bal.get("inbound_nat_rules", []), - inbound_nat_rules, - ["frontend_ip_configuration"], - ) - - if comp_ret.get("comment"): - ret["comment"] = '"inbound_nat_rules" {}'.format(comp_ret["comment"]) - return ret - - if comp_ret.get("changes"): - ret["changes"]["inbound_nat_rules"] = comp_ret["changes"] - - # inbound_nat_pools changes - if inbound_nat_pools: - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - load_bal.get("inbound_nat_pools", []), - inbound_nat_pools, - ["frontend_ip_configuration"], - ) - - if comp_ret.get("comment"): - ret["comment"] = '"inbound_nat_pools" {}'.format(comp_ret["comment"]) - return ret - - if comp_ret.get("changes"): - ret["changes"]["inbound_nat_pools"] = comp_ret["changes"] - - # outbound_nat_rules changes - if outbound_nat_rules: - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - load_bal.get("outbound_nat_rules", []), - outbound_nat_rules, - ["frontend_ip_configuration"], - ) - - if comp_ret.get("comment"): - ret["comment"] = '"outbound_nat_rules" {}'.format(comp_ret["comment"]) - return ret - - if comp_ret.get("changes"): - ret["changes"]["outbound_nat_rules"] = comp_ret["changes"] - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Load balancer {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Load balancer {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "sku": sku, - "tags": tags, - "frontend_ip_configurations": frontend_ip_configurations, - "backend_address_pools": backend_address_pools, - "load_balancing_rules": load_balancing_rules, - "probes": probes, - "inbound_nat_rules": inbound_nat_rules, - "inbound_nat_pools": inbound_nat_pools, - "outbound_nat_rules": outbound_nat_rules, - }, - } - - if __opts__["test"]: - ret["comment"] = "Load balancer {} would be created.".format(name) - ret["result"] = None - return ret - - lb_kwargs = kwargs.copy() - lb_kwargs.update(connection_auth) - - load_bal = __salt__["azurearm_network.load_balancer_create_or_update"]( - name=name, - resource_group=resource_group, - sku=sku, - tags=tags, - frontend_ip_configurations=frontend_ip_configurations, - backend_address_pools=backend_address_pools, - load_balancing_rules=load_balancing_rules, - probes=probes, - inbound_nat_rules=inbound_nat_rules, - inbound_nat_pools=inbound_nat_pools, - outbound_nat_rules=outbound_nat_rules, - **lb_kwargs - ) - - if "error" not in load_bal: - ret["result"] = True - ret["comment"] = "Load balancer {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create load balancer {}! ({})".format( - name, load_bal.get("error") - ) - return ret - - -@_deprecation_message -def load_balancer_absent(name, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a load balancer does not exist in the resource group. - - :param name: - Name of the load balancer. - - :param resource_group: - The resource group assigned to the load balancer. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - load_bal = __salt__["azurearm_network.load_balancer_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in load_bal: - ret["result"] = True - ret["comment"] = "Load balancer {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Load balancer {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": load_bal, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_network.load_balancer_delete"]( - name, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Load balancer {} has been deleted.".format(name) - ret["changes"] = {"old": load_bal, "new": {}} - return ret - - ret["comment"] = "Failed to delete load balancer {}!".format(name) - return ret - - -@_deprecation_message -def public_ip_address_present( - name, - resource_group, - tags=None, - sku=None, - public_ip_allocation_method=None, - public_ip_address_version=None, - dns_settings=None, - idle_timeout_in_minutes=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a public IP address exists. - - :param name: - Name of the public IP address. - - :param resource_group: - The resource group assigned to the public IP address. - - :param dns_settings: - An optional dictionary representing a valid PublicIPAddressDnsSettings object. Parameters include - 'domain_name_label' and 'reverse_fqdn', which accept strings. The 'domain_name_label' parameter is concatenated - with the regionalized DNS zone make up the fully qualified domain name associated with the public IP address. - If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS - system. The 'reverse_fqdn' parameter is a user-visible, fully qualified domain name that resolves to this public - IP address. If the reverse FQDN is specified, then a PTR DNS record is created pointing from the IP address in - the in-addr.arpa domain to the reverse FQDN. - - :param sku: - The public IP address SKU, which can be 'Basic' or 'Standard'. - - :param public_ip_allocation_method: - The public IP allocation method. Possible values are: 'Static' and 'Dynamic'. - - :param public_ip_address_version: - The public IP address version. Possible values are: 'IPv4' and 'IPv6'. - - :param idle_timeout_in_minutes: - An integer representing the idle timeout of the public IP address. - - :param tags: - A dictionary of strings can be passed as tag metadata to the public IP address object. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure public IP exists: - azurearm_network.public_ip_address_present: - - name: pub_ip1 - - resource_group: group1 - - dns_settings: - domain_name_label: decisionlab-ext-test-label - - sku: basic - - public_ip_allocation_method: static - - public_ip_address_version: ipv4 - - idle_timeout_in_minutes: 4 - - tags: - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - require: - - azurearm_resource: Ensure resource group exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - if sku: - sku = {"name": sku.capitalize()} - - pub_ip = __salt__["azurearm_network.public_ip_address_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" not in pub_ip: - # tag changes - tag_changes = __utils__["dictdiffer.deep_diff"]( - pub_ip.get("tags", {}), tags or {} - ) - if tag_changes: - ret["changes"]["tags"] = tag_changes - - # dns_settings changes - if dns_settings: - if not isinstance(dns_settings, dict): - ret["comment"] = "DNS settings must be provided as a dictionary!" - return ret - - for key in dns_settings: - if dns_settings[key] != pub_ip.get("dns_settings", {}).get(key): - ret["changes"]["dns_settings"] = { - "old": pub_ip.get("dns_settings"), - "new": dns_settings, - } - break - - # sku changes - if sku: - sku_changes = __utils__["dictdiffer.deep_diff"](pub_ip.get("sku", {}), sku) - if sku_changes: - ret["changes"]["sku"] = sku_changes - - # public_ip_allocation_method changes - if public_ip_allocation_method: - if public_ip_allocation_method.capitalize() != pub_ip.get( - "public_ip_allocation_method" - ): - ret["changes"]["public_ip_allocation_method"] = { - "old": pub_ip.get("public_ip_allocation_method"), - "new": public_ip_allocation_method, - } - - # public_ip_address_version changes - if public_ip_address_version: - if ( - public_ip_address_version.lower() - != pub_ip.get("public_ip_address_version", "").lower() - ): - ret["changes"]["public_ip_address_version"] = { - "old": pub_ip.get("public_ip_address_version"), - "new": public_ip_address_version, - } - - # idle_timeout_in_minutes changes - if idle_timeout_in_minutes and ( - int(idle_timeout_in_minutes) != pub_ip.get("idle_timeout_in_minutes") - ): - ret["changes"]["idle_timeout_in_minutes"] = { - "old": pub_ip.get("idle_timeout_in_minutes"), - "new": idle_timeout_in_minutes, - } - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Public IP address {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Public IP address {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "tags": tags, - "dns_settings": dns_settings, - "sku": sku, - "public_ip_allocation_method": public_ip_allocation_method, - "public_ip_address_version": public_ip_address_version, - "idle_timeout_in_minutes": idle_timeout_in_minutes, - }, - } - - if __opts__["test"]: - ret["comment"] = "Public IP address {} would be created.".format(name) - ret["result"] = None - return ret - - pub_ip_kwargs = kwargs.copy() - pub_ip_kwargs.update(connection_auth) - - pub_ip = __salt__["azurearm_network.public_ip_address_create_or_update"]( - name=name, - resource_group=resource_group, - sku=sku, - tags=tags, - dns_settings=dns_settings, - public_ip_allocation_method=public_ip_allocation_method, - public_ip_address_version=public_ip_address_version, - idle_timeout_in_minutes=idle_timeout_in_minutes, - **pub_ip_kwargs - ) - - if "error" not in pub_ip: - ret["result"] = True - ret["comment"] = "Public IP address {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create public IP address {}! ({})".format( - name, pub_ip.get("error") - ) - return ret - - -@_deprecation_message -def public_ip_address_absent(name, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a public IP address does not exist in the resource group. - - :param name: - Name of the public IP address. - - :param resource_group: - The resource group assigned to the public IP address. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - pub_ip = __salt__["azurearm_network.public_ip_address_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in pub_ip: - ret["result"] = True - ret["comment"] = "Public IP address {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Public IP address {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": pub_ip, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_network.public_ip_address_delete"]( - name, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Public IP address {} has been deleted.".format(name) - ret["changes"] = {"old": pub_ip, "new": {}} - return ret - - ret["comment"] = "Failed to delete public IP address {}!".format(name) - return ret - - -@_deprecation_message -def network_interface_present( - name, - ip_configurations, - subnet, - virtual_network, - resource_group, - tags=None, - virtual_machine=None, - network_security_group=None, - dns_settings=None, - mac_address=None, - primary=None, - enable_accelerated_networking=None, - enable_ip_forwarding=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a network interface exists. - - :param name: - Name of the network interface. - - :param ip_configurations: - A list of dictionaries representing valid NetworkInterfaceIPConfiguration objects. The 'name' key is required at - minimum. At least one IP Configuration must be present. - - :param subnet: - Name of the existing subnet assigned to the network interface. - - :param virtual_network: - Name of the existing virtual network containing the subnet. - - :param resource_group: - The resource group assigned to the virtual network. - - :param tags: - A dictionary of strings can be passed as tag metadata to the network interface object. - - :param network_security_group: - The name of the existing network security group to assign to the network interface. - - :param virtual_machine: - The name of the existing virtual machine to assign to the network interface. - - :param dns_settings: - An optional dictionary representing a valid NetworkInterfaceDnsSettings object. Valid parameters are: - - - ``dns_servers``: List of DNS server IP addresses. Use 'AzureProvidedDNS' to switch to Azure provided DNS - resolution. 'AzureProvidedDNS' value cannot be combined with other IPs, it must be the only value in - dns_servers collection. - - ``internal_dns_name_label``: Relative DNS name for this NIC used for internal communications between VMs in - the same virtual network. - - ``internal_fqdn``: Fully qualified DNS name supporting internal communications between VMs in the same virtual - network. - - ``internal_domain_name_suffix``: Even if internal_dns_name_label is not specified, a DNS entry is created for - the primary NIC of the VM. This DNS name can be constructed by concatenating the VM name with the value of - internal_domain_name_suffix. - - :param mac_address: - Optional string containing the MAC address of the network interface. - - :param primary: - Optional boolean allowing the interface to be set as the primary network interface on a virtual machine - with multiple interfaces attached. - - :param enable_accelerated_networking: - Optional boolean indicating whether accelerated networking should be enabled for the interface. - - :param enable_ip_forwarding: - Optional boolean indicating whether IP forwarding should be enabled for the interface. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure network interface exists: - azurearm_network.network_interface_present: - - name: iface1 - - subnet: vnet1_sn1 - - virtual_network: vnet1 - - resource_group: group1 - - ip_configurations: - - name: iface1_ipc1 - public_ip_address: pub_ip2 - - dns_settings: - internal_dns_name_label: decisionlab-int-test-label - - primary: True - - enable_accelerated_networking: True - - enable_ip_forwarding: False - - network_security_group: nsg1 - - connection_auth: {{ profile }} - - require: - - azurearm_network: Ensure subnet exists - - azurearm_network: Ensure network security group exists - - azurearm_network: Ensure another public IP exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - iface = __salt__["azurearm_network.network_interface_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" not in iface: - # tag changes - tag_changes = __utils__["dictdiffer.deep_diff"]( - iface.get("tags", {}), tags or {} - ) - if tag_changes: - ret["changes"]["tags"] = tag_changes - - # mac_address changes - if mac_address and (mac_address != iface.get("mac_address")): - ret["changes"]["mac_address"] = { - "old": iface.get("mac_address"), - "new": mac_address, - } - - # primary changes - if primary is not None: - if primary != iface.get("primary", True): - ret["changes"]["primary"] = { - "old": iface.get("primary"), - "new": primary, - } - - # enable_accelerated_networking changes - if enable_accelerated_networking is not None: - if enable_accelerated_networking != iface.get( - "enable_accelerated_networking" - ): - ret["changes"]["enable_accelerated_networking"] = { - "old": iface.get("enable_accelerated_networking"), - "new": enable_accelerated_networking, - } - - # enable_ip_forwarding changes - if enable_ip_forwarding is not None: - if enable_ip_forwarding != iface.get("enable_ip_forwarding"): - ret["changes"]["enable_ip_forwarding"] = { - "old": iface.get("enable_ip_forwarding"), - "new": enable_ip_forwarding, - } - - # network_security_group changes - nsg_name = None - if iface.get("network_security_group"): - nsg_name = iface["network_security_group"]["id"].split("/")[-1] - - if network_security_group and (network_security_group != nsg_name): - ret["changes"]["network_security_group"] = { - "old": nsg_name, - "new": network_security_group, - } - - # virtual_machine changes - vm_name = None - if iface.get("virtual_machine"): - vm_name = iface["virtual_machine"]["id"].split("/")[-1] - - if virtual_machine and (virtual_machine != vm_name): - ret["changes"]["virtual_machine"] = {"old": vm_name, "new": virtual_machine} - - # dns_settings changes - if dns_settings: - if not isinstance(dns_settings, dict): - ret["comment"] = "DNS settings must be provided as a dictionary!" - return ret - - for key in dns_settings: - if ( - dns_settings[key].lower() - != iface.get("dns_settings", {}).get(key, "").lower() - ): - ret["changes"]["dns_settings"] = { - "old": iface.get("dns_settings"), - "new": dns_settings, - } - break - - # ip_configurations changes - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - iface.get("ip_configurations", []), - ip_configurations, - ["public_ip_address", "subnet"], - ) - - if comp_ret.get("comment"): - ret["comment"] = '"ip_configurations" {}'.format(comp_ret["comment"]) - return ret - - if comp_ret.get("changes"): - ret["changes"]["ip_configurations"] = comp_ret["changes"] - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Network interface {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Network interface {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "ip_configurations": ip_configurations, - "dns_settings": dns_settings, - "network_security_group": network_security_group, - "virtual_machine": virtual_machine, - "enable_accelerated_networking": enable_accelerated_networking, - "enable_ip_forwarding": enable_ip_forwarding, - "mac_address": mac_address, - "primary": primary, - "tags": tags, - }, - } - - if __opts__["test"]: - ret["comment"] = "Network interface {} would be created.".format(name) - ret["result"] = None - return ret - - iface_kwargs = kwargs.copy() - iface_kwargs.update(connection_auth) - - iface = __salt__["azurearm_network.network_interface_create_or_update"]( - name=name, - subnet=subnet, - virtual_network=virtual_network, - resource_group=resource_group, - ip_configurations=ip_configurations, - dns_settings=dns_settings, - enable_accelerated_networking=enable_accelerated_networking, - enable_ip_forwarding=enable_ip_forwarding, - mac_address=mac_address, - primary=primary, - network_security_group=network_security_group, - virtual_machine=virtual_machine, - tags=tags, - **iface_kwargs - ) - - if "error" not in iface: - ret["result"] = True - ret["comment"] = "Network interface {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create network interface {}! ({})".format( - name, iface.get("error") - ) - return ret - - -@_deprecation_message -def network_interface_absent(name, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a network interface does not exist in the resource group. - - :param name: - Name of the network interface. - - :param resource_group: - The resource group assigned to the network interface. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - iface = __salt__["azurearm_network.network_interface_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in iface: - ret["result"] = True - ret["comment"] = "Network interface {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Network interface {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": iface, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_network.network_interface_delete"]( - name, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Network interface {} has been deleted.".format(name) - ret["changes"] = {"old": iface, "new": {}} - return ret - - ret["comment"] = "Failed to delete network interface {}!)".format(name) - return ret - - -@_deprecation_message -def route_table_present( - name, - resource_group, - tags=None, - routes=None, - disable_bgp_route_propagation=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a route table exists. - - :param name: - Name of the route table. - - :param resource_group: - The resource group assigned to the route table. - - :param routes: - An optional list of dictionaries representing valid Route objects contained within a route table. See the - documentation for the route_present state or route_create_or_update execution module for more information on - required and optional parameters for routes. The routes are only managed if this parameter is present. When this - parameter is absent, implemented routes will not be removed, and will merely become unmanaged. - - :param disable_bgp_route_propagation: - An optional boolean parameter setting whether to disable the routes learned by BGP on the route table. - - :param tags: - A dictionary of strings can be passed as tag metadata to the route table object. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure route table exists: - azurearm_network.route_table_present: - - name: rt1 - - resource_group: group1 - - routes: - - name: rt1_route1 - address_prefix: '0.0.0.0/0' - next_hop_type: internet - - name: rt1_route2 - address_prefix: '192.168.0.0/16' - next_hop_type: vnetlocal - - tags: - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - require: - - azurearm_resource: Ensure resource group exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - rt_tbl = __salt__["azurearm_network.route_table_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" not in rt_tbl: - # tag changes - tag_changes = __utils__["dictdiffer.deep_diff"]( - rt_tbl.get("tags", {}), tags or {} - ) - if tag_changes: - ret["changes"]["tags"] = tag_changes - - # disable_bgp_route_propagation changes - # pylint: disable=line-too-long - if disable_bgp_route_propagation and ( - disable_bgp_route_propagation != rt_tbl.get("disable_bgp_route_propagation") - ): - ret["changes"]["disable_bgp_route_propagation"] = { - "old": rt_tbl.get("disable_bgp_route_propagation"), - "new": disable_bgp_route_propagation, - } - - # routes changes - if routes: - comp_ret = __utils__["azurearm.compare_list_of_dicts"]( - rt_tbl.get("routes", []), routes - ) - - if comp_ret.get("comment"): - ret["comment"] = '"routes" {}'.format(comp_ret["comment"]) - return ret - - if comp_ret.get("changes"): - ret["changes"]["routes"] = comp_ret["changes"] - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Route table {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Route table {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "tags": tags, - "routes": routes, - "disable_bgp_route_propagation": disable_bgp_route_propagation, - }, - } - - if __opts__["test"]: - ret["comment"] = "Route table {} would be created.".format(name) - ret["result"] = None - return ret - - rt_tbl_kwargs = kwargs.copy() - rt_tbl_kwargs.update(connection_auth) - - rt_tbl = __salt__["azurearm_network.route_table_create_or_update"]( - name=name, - resource_group=resource_group, - disable_bgp_route_propagation=disable_bgp_route_propagation, - routes=routes, - tags=tags, - **rt_tbl_kwargs - ) - - if "error" not in rt_tbl: - ret["result"] = True - ret["comment"] = "Route table {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create route table {}! ({})".format( - name, rt_tbl.get("error") - ) - return ret - - -@_deprecation_message -def route_table_absent(name, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a route table does not exist in the resource group. - - :param name: - Name of the route table. - - :param resource_group: - The resource group assigned to the route table. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - rt_tbl = __salt__["azurearm_network.route_table_get"]( - name, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in rt_tbl: - ret["result"] = True - ret["comment"] = "Route table {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Route table {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": rt_tbl, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_network.route_table_delete"]( - name, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Route table {} has been deleted.".format(name) - ret["changes"] = {"old": rt_tbl, "new": {}} - return ret - - ret["comment"] = "Failed to delete route table {}!".format(name) - return ret - - -@_deprecation_message -def route_present( - name, - address_prefix, - next_hop_type, - route_table, - resource_group, - next_hop_ip_address=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a route exists within a route table. - - :param name: - Name of the route. - - :param address_prefix: - The destination CIDR to which the route applies. - - :param next_hop_type: - The type of Azure hop the packet should be sent to. Possible values are: 'VirtualNetworkGateway', 'VnetLocal', - 'Internet', 'VirtualAppliance', and 'None'. - - :param next_hop_ip_address: - The IP address packets should be forwarded to. Next hop values are only allowed in routes where the next hop - type is 'VirtualAppliance'. - - :param route_table: - The name of the existing route table which will contain the route. - - :param resource_group: - The resource group assigned to the route table. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure route exists: - azurearm_network.route_present: - - name: rt1_route2 - - route_table: rt1 - - resource_group: group1 - - address_prefix: '192.168.0.0/16' - - next_hop_type: vnetlocal - - connection_auth: {{ profile }} - - require: - - azurearm_network: Ensure route table exists - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - route = __salt__["azurearm_network.route_get"]( - name, route_table, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" not in route: - if address_prefix != route.get("address_prefix"): - ret["changes"]["address_prefix"] = { - "old": route.get("address_prefix"), - "new": address_prefix, - } - - if next_hop_type.lower() != route.get("next_hop_type", "").lower(): - ret["changes"]["next_hop_type"] = { - "old": route.get("next_hop_type"), - "new": next_hop_type, - } - - if ( - next_hop_type.lower() == "virtualappliance" - and next_hop_ip_address != route.get("next_hop_ip_address") - ): - ret["changes"]["next_hop_ip_address"] = { - "old": route.get("next_hop_ip_address"), - "new": next_hop_ip_address, - } - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Route {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["result"] = None - ret["comment"] = "Route {} would be updated.".format(name) - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "address_prefix": address_prefix, - "next_hop_type": next_hop_type, - "next_hop_ip_address": next_hop_ip_address, - }, - } - - if __opts__["test"]: - ret["comment"] = "Route {} would be created.".format(name) - ret["result"] = None - return ret - - route_kwargs = kwargs.copy() - route_kwargs.update(connection_auth) - - route = __salt__["azurearm_network.route_create_or_update"]( - name=name, - route_table=route_table, - resource_group=resource_group, - address_prefix=address_prefix, - next_hop_type=next_hop_type, - next_hop_ip_address=next_hop_ip_address, - **route_kwargs - ) - - if "error" not in route: - ret["result"] = True - ret["comment"] = "Route {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create route {}! ({})".format(name, route.get("error")) - return ret - - -@_deprecation_message -def route_absent(name, route_table, resource_group, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a route table does not exist in the resource group. - - :param name: - Name of the route table. - - :param route_table: - The name of the existing route table containing the route. - - :param resource_group: - The resource group assigned to the route table. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - route = __salt__["azurearm_network.route_get"]( - name, route_table, resource_group, azurearm_log_level="info", **connection_auth - ) - - if "error" in route: - ret["result"] = True - ret["comment"] = "Route {} was not found.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Route {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": route, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_network.route_delete"]( - name, route_table, resource_group, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Route {} has been deleted.".format(name) - ret["changes"] = {"old": route, "new": {}} - return ret - - ret["comment"] = "Failed to delete route {}!".format(name) - return ret diff --git a/salt/states/azurearm_resource.py b/salt/states/azurearm_resource.py deleted file mode 100644 index 7cef3bc0bd9..00000000000 --- a/salt/states/azurearm_resource.py +++ /dev/null @@ -1,880 +0,0 @@ -""" -Azure (ARM) Resource State Module - -.. versionadded:: 2019.2.0 - -.. warning:: - - This cloud provider will be removed from Salt in version 3007 in favor of - the `saltext.azurerm Salt Extension - `_ - -:maintainer: -:maturity: new -:depends: - * `azure `_ >= 2.0.0 - * `azure-common `_ >= 1.1.8 - * `azure-mgmt `_ >= 1.0.0 - * `azure-mgmt-compute `_ >= 1.0.0 - * `azure-mgmt-network `_ >= 1.7.1 - * `azure-mgmt-resource `_ >= 1.1.0 - * `azure-mgmt-storage `_ >= 1.0.0 - * `azure-mgmt-web `_ >= 0.32.0 - * `azure-storage `_ >= 0.34.3 - * `msrestazure `_ >= 0.4.21 -:platform: linux - -:configuration: This module requires Azure Resource Manager credentials to be passed as a dictionary of - keyword arguments to the ``connection_auth`` parameter in order to work properly. Since the authentication - parameters are sensitive, it's recommended to pass them to the states via pillar. - - Required provider parameters: - - if using username and password: - * ``subscription_id`` - * ``username`` - * ``password`` - - if using a service principal: - * ``subscription_id`` - * ``tenant`` - * ``client_id`` - * ``secret`` - - Optional provider parameters: - - **cloud_environment**: Used to point the cloud driver to different API endpoints, such as Azure GovCloud. Possible values: - * ``AZURE_PUBLIC_CLOUD`` (default) - * ``AZURE_CHINA_CLOUD`` - * ``AZURE_US_GOV_CLOUD`` - * ``AZURE_GERMAN_CLOUD`` - - Example Pillar for Azure Resource Manager authentication: - - .. code-block:: yaml - - azurearm: - user_pass_auth: - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - username: fletch - password: 123pass - mysubscription: - subscription_id: 3287abc8-f98a-c678-3bde-326766fd3617 - tenant: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - client_id: ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF - secret: XXXXXXXXXXXXXXXXXXXXXXXX - cloud_environment: AZURE_PUBLIC_CLOUD - - Example states using Azure Resource Manager authentication: - - .. code-block:: jinja - - {% set profile = salt['pillar.get']('azurearm:mysubscription') %} - Ensure resource group exists: - azurearm_resource.resource_group_present: - - name: my_rg - - location: westus - - tags: - how_awesome: very - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - Ensure resource group is absent: - azurearm_resource.resource_group_absent: - - name: other_rg - - connection_auth: {{ profile }} - -""" - - -import json -import logging -from functools import wraps - -import salt.utils.azurearm -import salt.utils.files - -__virtualname__ = "azurearm_resource" - -log = logging.getLogger(__name__) - - -def __virtual__(): - """ - Only make this state available if the azurearm_resource module is available. - """ - if "azurearm_resource.resource_group_check_existence" in __salt__: - return __virtualname__ - return (False, "azurearm_resource module could not be loaded") - - -def _deprecation_message(function): - """ - Decorator wrapper to warn about azurearm deprecation - """ - - @wraps(function) - def wrapped(*args, **kwargs): - salt.utils.versions.warn_until( - "Chlorine", - "The 'azurearm' functionality in Salt has been deprecated and its " - "functionality will be removed in version 3007 in favor of the " - "saltext.azurerm Salt Extension. " - "(https://github.com/salt-extensions/saltext-azurerm)", - category=FutureWarning, - ) - ret = function(*args, **salt.utils.args.clean_kwargs(**kwargs)) - return ret - - return wrapped - - -@_deprecation_message -def resource_group_present( - name, location, managed_by=None, tags=None, connection_auth=None, **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a resource group exists. - - :param name: - Name of the resource group. - - :param location: - The Azure location in which to create the resource group. This value cannot be updated once - the resource group is created. - - :param managed_by: - The ID of the resource that manages this resource group. This value cannot be updated once - the resource group is created. - - :param tags: - A dictionary of strings can be passed as tag metadata to the resource group object. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure resource group exists: - azurearm_resource.resource_group_present: - - name: group1 - - location: eastus - - tags: - contact_name: Elmer Fudd Gantry - - connection_auth: {{ profile }} - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - group = {} - - present = __salt__["azurearm_resource.resource_group_check_existence"]( - name, **connection_auth - ) - - if present: - group = __salt__["azurearm_resource.resource_group_get"]( - name, **connection_auth - ) - ret["changes"] = __utils__["dictdiffer.deep_diff"]( - group.get("tags", {}), tags or {} - ) - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Resource group {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["comment"] = "Resource group {} tags would be updated.".format(name) - ret["result"] = None - ret["changes"] = {"old": group.get("tags", {}), "new": tags} - return ret - - elif __opts__["test"]: - ret["comment"] = "Resource group {} would be created.".format(name) - ret["result"] = None - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "location": location, - "managed_by": managed_by, - "tags": tags, - }, - } - return ret - - group_kwargs = kwargs.copy() - group_kwargs.update(connection_auth) - - group = __salt__["azurearm_resource.resource_group_create_or_update"]( - name, location, managed_by=managed_by, tags=tags, **group_kwargs - ) - present = __salt__["azurearm_resource.resource_group_check_existence"]( - name, **connection_auth - ) - - if present: - ret["result"] = True - ret["comment"] = "Resource group {} has been created.".format(name) - ret["changes"] = {"old": {}, "new": group} - return ret - - ret["comment"] = "Failed to create resource group {}! ({})".format( - name, group.get("error") - ) - return ret - - -@_deprecation_message -def resource_group_absent(name, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a resource group does not exist in the current subscription. - - :param name: - Name of the resource group. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - group = {} - - present = __salt__["azurearm_resource.resource_group_check_existence"]( - name, **connection_auth - ) - - if not present: - ret["result"] = True - ret["comment"] = "Resource group {} is already absent.".format(name) - return ret - - elif __opts__["test"]: - group = __salt__["azurearm_resource.resource_group_get"]( - name, **connection_auth - ) - - ret["comment"] = "Resource group {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": group, - "new": {}, - } - return ret - - group = __salt__["azurearm_resource.resource_group_get"](name, **connection_auth) - deleted = __salt__["azurearm_resource.resource_group_delete"]( - name, **connection_auth - ) - - if deleted: - present = False - else: - present = __salt__["azurearm_resource.resource_group_check_existence"]( - name, **connection_auth - ) - - if not present: - ret["result"] = True - ret["comment"] = "Resource group {} has been deleted.".format(name) - ret["changes"] = {"old": group, "new": {}} - return ret - - ret["comment"] = "Failed to delete resource group {}!".format(name) - return ret - - -@_deprecation_message -def policy_definition_present( - name, - policy_rule=None, - policy_type=None, - mode=None, - display_name=None, - description=None, - metadata=None, - parameters=None, - policy_rule_json=None, - policy_rule_file=None, - template="jinja", - source_hash=None, - source_hash_name=None, - skip_verify=False, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a security policy definition exists. - - :param name: - Name of the policy definition. - - :param policy_rule: - A YAML dictionary defining the policy rule. See `Azure Policy Definition documentation - `_ for details on the - structure. One of ``policy_rule``, ``policy_rule_json``, or ``policy_rule_file`` is required, in that order of - precedence for use if multiple parameters are used. - - :param policy_rule_json: - A text field defining the entirety of a policy definition in JSON. See `Azure Policy Definition documentation - `_ for details on the - structure. One of ``policy_rule``, ``policy_rule_json``, or ``policy_rule_file`` is required, in that order of - precedence for use if multiple parameters are used. Note that the `name` field in the JSON will override the - ``name`` parameter in the state. - - :param policy_rule_file: - The source of a JSON file defining the entirety of a policy definition. See `Azure Policy Definition - documentation `_ for - details on the structure. One of ``policy_rule``, ``policy_rule_json``, or ``policy_rule_file`` is required, - in that order of precedence for use if multiple parameters are used. Note that the `name` field in the JSON - will override the ``name`` parameter in the state. - - :param skip_verify: - Used for the ``policy_rule_file`` parameter. If ``True``, hash verification of remote file sources - (``http://``, ``https://``, ``ftp://``) will be skipped, and the ``source_hash`` argument will be ignored. - - :param source_hash: - This can be a source hash string or the URI of a file that contains source hash strings. - - :param source_hash_name: - When ``source_hash`` refers to a hash file, Salt will try to find the correct hash by matching the - filename/URI associated with that hash. - - :param policy_type: - The type of policy definition. Possible values are NotSpecified, BuiltIn, and Custom. Only used with the - ``policy_rule`` parameter. - - :param mode: - The policy definition mode. Possible values are NotSpecified, Indexed, and All. Only used with the - ``policy_rule`` parameter. - - :param display_name: - The display name of the policy definition. Only used with the ``policy_rule`` parameter. - - :param description: - The policy definition description. Only used with the ``policy_rule`` parameter. - - :param metadata: - The policy definition metadata defined as a dictionary. Only used with the ``policy_rule`` parameter. - - :param parameters: - Required dictionary if a parameter is used in the policy rule. Only used with the ``policy_rule`` parameter. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure policy definition exists: - azurearm_resource.policy_definition_present: - - name: testpolicy - - display_name: Test Policy - - description: Test policy for testing policies. - - policy_rule: - if: - allOf: - - equals: Microsoft.Compute/virtualMachines/write - source: action - - field: location - in: - - eastus - - eastus2 - - centralus - then: - effect: deny - - connection_auth: {{ profile }} - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - if not policy_rule and not policy_rule_json and not policy_rule_file: - ret["comment"] = ( - 'One of "policy_rule", "policy_rule_json", or "policy_rule_file" is' - " required!" - ) - return ret - - if ( - sum(x is not None for x in [policy_rule, policy_rule_json, policy_rule_file]) - > 1 - ): - ret["comment"] = ( - 'Only one of "policy_rule", "policy_rule_json", or "policy_rule_file" is' - " allowed!" - ) - return ret - - if (policy_rule_json or policy_rule_file) and ( - policy_type or mode or display_name or description or metadata or parameters - ): - ret["comment"] = ( - 'Policy definitions cannot be passed when "policy_rule_json" or' - ' "policy_rule_file" is defined!' - ) - return ret - - temp_rule = {} - if policy_rule_json: - try: - temp_rule = json.loads(policy_rule_json) - except Exception as exc: # pylint: disable=broad-except - ret["comment"] = "Unable to load policy rule json! ({})".format(exc) - return ret - elif policy_rule_file: - try: - # pylint: disable=unused-variable - sfn, source_sum, comment_ = __salt__["file.get_managed"]( - None, - template, - policy_rule_file, - source_hash, - source_hash_name, - None, - None, - None, - __env__, - None, - None, - skip_verify=skip_verify, - **kwargs - ) - except Exception as exc: # pylint: disable=broad-except - ret["comment"] = 'Unable to locate policy rule file "{}"! ({})'.format( - policy_rule_file, exc - ) - return ret - - if not sfn: - ret["comment"] = 'Unable to locate policy rule file "{}"!)'.format( - policy_rule_file - ) - return ret - - try: - with salt.utils.files.fopen(sfn, "r") as prf: - temp_rule = json.load(prf) - except Exception as exc: # pylint: disable=broad-except - ret["comment"] = 'Unable to load policy rule file "{}"! ({})'.format( - policy_rule_file, exc - ) - return ret - - if sfn: - salt.utils.files.remove(sfn) - - policy_name = name - if policy_rule_json or policy_rule_file: - if temp_rule.get("name"): - policy_name = temp_rule.get("name") - policy_rule = temp_rule.get("properties", {}).get("policyRule") - policy_type = temp_rule.get("properties", {}).get("policyType") - mode = temp_rule.get("properties", {}).get("mode") - display_name = temp_rule.get("properties", {}).get("displayName") - description = temp_rule.get("properties", {}).get("description") - metadata = temp_rule.get("properties", {}).get("metadata") - parameters = temp_rule.get("properties", {}).get("parameters") - - policy = __salt__["azurearm_resource.policy_definition_get"]( - name, azurearm_log_level="info", **connection_auth - ) - - if "error" not in policy: - if policy_type and policy_type.lower() != policy.get("policy_type", "").lower(): - ret["changes"]["policy_type"] = { - "old": policy.get("policy_type"), - "new": policy_type, - } - - if (mode or "").lower() != policy.get("mode", "").lower(): - ret["changes"]["mode"] = {"old": policy.get("mode"), "new": mode} - - if (display_name or "").lower() != policy.get("display_name", "").lower(): - ret["changes"]["display_name"] = { - "old": policy.get("display_name"), - "new": display_name, - } - - if (description or "").lower() != policy.get("description", "").lower(): - ret["changes"]["description"] = { - "old": policy.get("description"), - "new": description, - } - - rule_changes = __utils__["dictdiffer.deep_diff"]( - policy.get("policy_rule", {}), policy_rule or {} - ) - if rule_changes: - ret["changes"]["policy_rule"] = rule_changes - - meta_changes = __utils__["dictdiffer.deep_diff"]( - policy.get("metadata", {}), metadata or {} - ) - if meta_changes: - ret["changes"]["metadata"] = meta_changes - - param_changes = __utils__["dictdiffer.deep_diff"]( - policy.get("parameters", {}), parameters or {} - ) - if param_changes: - ret["changes"]["parameters"] = param_changes - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Policy definition {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["comment"] = "Policy definition {} would be updated.".format(name) - ret["result"] = None - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": policy_name, - "policy_type": policy_type, - "mode": mode, - "display_name": display_name, - "description": description, - "metadata": metadata, - "parameters": parameters, - "policy_rule": policy_rule, - }, - } - - if __opts__["test"]: - ret["comment"] = "Policy definition {} would be created.".format(name) - ret["result"] = None - return ret - - # Convert OrderedDict to dict - if isinstance(metadata, dict): - metadata = json.loads(json.dumps(metadata)) - if isinstance(parameters, dict): - parameters = json.loads(json.dumps(parameters)) - - policy_kwargs = kwargs.copy() - policy_kwargs.update(connection_auth) - - policy = __salt__["azurearm_resource.policy_definition_create_or_update"]( - name=policy_name, - policy_rule=policy_rule, - policy_type=policy_type, - mode=mode, - display_name=display_name, - description=description, - metadata=metadata, - parameters=parameters, - **policy_kwargs - ) - - if "error" not in policy: - ret["result"] = True - ret["comment"] = "Policy definition {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create policy definition {}! ({})".format( - name, policy.get("error") - ) - return ret - - -@_deprecation_message -def policy_definition_absent(name, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a policy definition does not exist in the current subscription. - - :param name: - Name of the policy definition. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - policy = __salt__["azurearm_resource.policy_definition_get"]( - name, azurearm_log_level="info", **connection_auth - ) - - if "error" in policy: - ret["result"] = True - ret["comment"] = "Policy definition {} is already absent.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Policy definition {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": policy, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_resource.policy_definition_delete"]( - name, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Policy definition {} has been deleted.".format(name) - ret["changes"] = {"old": policy, "new": {}} - return ret - - ret["comment"] = "Failed to delete policy definition {}!".format(name) - return ret - - -@_deprecation_message -def policy_assignment_present( - name, - scope, - definition_name, - display_name=None, - description=None, - assignment_type=None, - parameters=None, - connection_auth=None, - **kwargs -): - """ - .. versionadded:: 2019.2.0 - - Ensure a security policy assignment exists. - - :param name: - Name of the policy assignment. - - :param scope: - The scope of the policy assignment. - - :param definition_name: - The name of the policy definition to assign. - - :param display_name: - The display name of the policy assignment. - - :param description: - The policy assignment description. - - :param assignment_type: - The type of policy assignment. - - :param parameters: - Required dictionary if a parameter is used in the policy rule. - - :param connection_auth: - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - - Example usage: - - .. code-block:: yaml - - Ensure policy assignment exists: - azurearm_resource.policy_assignment_present: - - name: testassign - - scope: /subscriptions/bc75htn-a0fhsi-349b-56gh-4fghti-f84852 - - definition_name: testpolicy - - display_name: Test Assignment - - description: Test assignment for testing assignments. - - connection_auth: {{ profile }} - - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - policy = __salt__["azurearm_resource.policy_assignment_get"]( - name, scope, azurearm_log_level="info", **connection_auth - ) - - if "error" not in policy: - if ( - assignment_type - and assignment_type.lower() != policy.get("type", "").lower() - ): - ret["changes"]["type"] = {"old": policy.get("type"), "new": assignment_type} - - if scope.lower() != policy["scope"].lower(): - ret["changes"]["scope"] = {"old": policy["scope"], "new": scope} - - pa_name = policy["policy_definition_id"].split("/")[-1] - if definition_name.lower() != pa_name.lower(): - ret["changes"]["definition_name"] = {"old": pa_name, "new": definition_name} - - if (display_name or "").lower() != policy.get("display_name", "").lower(): - ret["changes"]["display_name"] = { - "old": policy.get("display_name"), - "new": display_name, - } - - if (description or "").lower() != policy.get("description", "").lower(): - ret["changes"]["description"] = { - "old": policy.get("description"), - "new": description, - } - - param_changes = __utils__["dictdiffer.deep_diff"]( - policy.get("parameters", {}), parameters or {} - ) - if param_changes: - ret["changes"]["parameters"] = param_changes - - if not ret["changes"]: - ret["result"] = True - ret["comment"] = "Policy assignment {} is already present.".format(name) - return ret - - if __opts__["test"]: - ret["comment"] = "Policy assignment {} would be updated.".format(name) - ret["result"] = None - return ret - - else: - ret["changes"] = { - "old": {}, - "new": { - "name": name, - "scope": scope, - "definition_name": definition_name, - "type": assignment_type, - "display_name": display_name, - "description": description, - "parameters": parameters, - }, - } - - if __opts__["test"]: - ret["comment"] = "Policy assignment {} would be created.".format(name) - ret["result"] = None - return ret - - if isinstance(parameters, dict): - parameters = json.loads(json.dumps(parameters)) - - policy_kwargs = kwargs.copy() - policy_kwargs.update(connection_auth) - policy = __salt__["azurearm_resource.policy_assignment_create"]( - name=name, - scope=scope, - definition_name=definition_name, - type=assignment_type, - display_name=display_name, - description=description, - parameters=parameters, - **policy_kwargs - ) - - if "error" not in policy: - ret["result"] = True - ret["comment"] = "Policy assignment {} has been created.".format(name) - return ret - - ret["comment"] = "Failed to create policy assignment {}! ({})".format( - name, policy.get("error") - ) - return ret - - -@_deprecation_message -def policy_assignment_absent(name, scope, connection_auth=None): - """ - .. versionadded:: 2019.2.0 - - Ensure a policy assignment does not exist in the provided scope. - - :param name: - Name of the policy assignment. - - :param scope: - The scope of the policy assignment. - - connection_auth - A dict with subscription and authentication parameters to be used in connecting to the - Azure Resource Manager API. - """ - ret = {"name": name, "result": False, "comment": "", "changes": {}} - - if not isinstance(connection_auth, dict): - ret[ - "comment" - ] = "Connection information must be specified via connection_auth dictionary!" - return ret - - policy = __salt__["azurearm_resource.policy_assignment_get"]( - name, scope, azurearm_log_level="info", **connection_auth - ) - - if "error" in policy: - ret["result"] = True - ret["comment"] = "Policy assignment {} is already absent.".format(name) - return ret - - elif __opts__["test"]: - ret["comment"] = "Policy assignment {} would be deleted.".format(name) - ret["result"] = None - ret["changes"] = { - "old": policy, - "new": {}, - } - return ret - - deleted = __salt__["azurearm_resource.policy_assignment_delete"]( - name, scope, **connection_auth - ) - - if deleted: - ret["result"] = True - ret["comment"] = "Policy assignment {} has been deleted.".format(name) - ret["changes"] = {"old": policy, "new": {}} - return ret - - ret["comment"] = "Failed to delete policy assignment {}!".format(name) - return ret diff --git a/salt/utils/azurearm.py b/salt/utils/azurearm.py deleted file mode 100644 index 276cbb66b36..00000000000 --- a/salt/utils/azurearm.py +++ /dev/null @@ -1,338 +0,0 @@ -""" -Azure (ARM) Utilities - -.. versionadded:: 2019.2.0 - -:maintainer: -:maturity: new -:depends: - * `azure `_ >= 2.0.0rc6 - * `azure-common `_ >= 1.1.4 - * `azure-mgmt `_ >= 0.30.0rc6 - * `azure-mgmt-compute `_ >= 0.33.0 - * `azure-mgmt-network `_ >= 0.30.0rc6 - * `azure-mgmt-resource `_ >= 0.30.0 - * `azure-mgmt-storage `_ >= 0.30.0rc6 - * `azure-mgmt-web `_ >= 0.30.0rc6 - * `azure-storage `_ >= 0.32.0 - * `msrestazure `_ >= 0.4.21 -:platform: linux - -""" - -import importlib -import logging -import sys -from operator import itemgetter - -import salt.config -import salt.loader -import salt.utils.args -import salt.utils.stringutils -import salt.utils.versions -import salt.version -from salt.exceptions import SaltInvocationError, SaltSystemExit - -try: - from azure.common.credentials import ( - ServicePrincipalCredentials, - UserPassCredentials, - ) - from msrestazure.azure_cloud import ( - MetadataEndpointError, - get_cloud_from_metadata_endpoint, - ) - - HAS_AZURE = True -except ImportError: - HAS_AZURE = False - -__opts__ = salt.config.minion_config("/etc/salt/minion") -__salt__ = salt.loader.minion_mods(__opts__) - -log = logging.getLogger(__name__) - - -def __virtual__(): - if not HAS_AZURE: - return False - else: - return True - - -def _determine_auth(**kwargs): - """ - Acquire Azure ARM Credentials - """ - if "profile" in kwargs: - azure_credentials = __salt__["config.option"](kwargs["profile"]) - kwargs.update(azure_credentials) - - service_principal_creds_kwargs = ["client_id", "secret", "tenant"] - user_pass_creds_kwargs = ["username", "password"] - - try: - if kwargs.get("cloud_environment") and kwargs.get( - "cloud_environment" - ).startswith("http"): - cloud_env = get_cloud_from_metadata_endpoint(kwargs["cloud_environment"]) - else: - cloud_env_module = importlib.import_module("msrestazure.azure_cloud") - cloud_env = getattr( - cloud_env_module, kwargs.get("cloud_environment", "AZURE_PUBLIC_CLOUD") - ) - except (AttributeError, ImportError, MetadataEndpointError): - raise sys.exit( - "The Azure cloud environment {} is not available.".format( - kwargs["cloud_environment"] - ) - ) - - if set(service_principal_creds_kwargs).issubset(kwargs): - if not (kwargs["client_id"] and kwargs["secret"] and kwargs["tenant"]): - raise SaltInvocationError( - "The client_id, secret, and tenant parameters must all be " - "populated if using service principals." - ) - else: - credentials = ServicePrincipalCredentials( - kwargs["client_id"], - kwargs["secret"], - tenant=kwargs["tenant"], - cloud_environment=cloud_env, - ) - elif set(user_pass_creds_kwargs).issubset(kwargs): - if not (kwargs["username"] and kwargs["password"]): - raise SaltInvocationError( - "The username and password parameters must both be " - "populated if using username/password authentication." - ) - else: - credentials = UserPassCredentials( - kwargs["username"], kwargs["password"], cloud_environment=cloud_env - ) - elif "subscription_id" in kwargs: - try: - from msrestazure.azure_active_directory import MSIAuthentication - - credentials = MSIAuthentication(cloud_environment=cloud_env) - except ImportError: - raise SaltSystemExit( - msg=( - "MSI authentication support not availabe (requires msrestazure >=" - " 0.4.14)" - ) - ) - - else: - raise SaltInvocationError( - "Unable to determine credentials. " - "A subscription_id with username and password, " - "or client_id, secret, and tenant or a profile with the " - "required parameters populated" - ) - - if "subscription_id" not in kwargs: - raise SaltInvocationError("A subscription_id must be specified") - - subscription_id = salt.utils.stringutils.to_str(kwargs["subscription_id"]) - - return credentials, subscription_id, cloud_env - - -def get_client(client_type, **kwargs): - """ - Dynamically load the selected client and return a management client object - """ - client_map = { - "compute": "ComputeManagement", - "authorization": "AuthorizationManagement", - "dns": "DnsManagement", - "storage": "StorageManagement", - "managementlock": "ManagementLock", - "monitor": "MonitorManagement", - "network": "NetworkManagement", - "policy": "Policy", - "resource": "ResourceManagement", - "subscription": "Subscription", - "web": "WebSiteManagement", - } - - if client_type not in client_map: - raise SaltSystemExit( - msg="The Azure ARM client_type {} specified can not be found.".format( - client_type - ) - ) - - map_value = client_map[client_type] - - if client_type in ["policy", "subscription"]: - module_name = "resource" - elif client_type in ["managementlock"]: - module_name = "resource.locks" - else: - module_name = client_type - - try: - client_module = importlib.import_module("azure.mgmt." + module_name) - # pylint: disable=invalid-name - Client = getattr(client_module, "{}Client".format(map_value)) - except ImportError: - raise sys.exit("The azure {} client is not available.".format(client_type)) - - credentials, subscription_id, cloud_env = _determine_auth(**kwargs) - - if client_type == "subscription": - client = Client( - credentials=credentials, - base_url=cloud_env.endpoints.resource_manager, - ) - else: - client = Client( - credentials=credentials, - subscription_id=subscription_id, - base_url=cloud_env.endpoints.resource_manager, - ) - - client.config.add_user_agent("Salt/{}".format(salt.version.__version__)) - - return client - - -def log_cloud_error(client, message, **kwargs): - """ - Log an azurearm cloud error exception - """ - try: - cloud_logger = getattr(log, kwargs.get("azurearm_log_level")) - except (AttributeError, TypeError): - cloud_logger = getattr(log, "error") - - cloud_logger( - "An AzureARM %s CloudError has occurred: %s", client.capitalize(), message - ) - - return - - -def paged_object_to_list(paged_object): - """ - Extract all pages within a paged object as a list of dictionaries - """ - paged_return = [] - while True: - try: - page = next(paged_object) - paged_return.append(page.as_dict()) - except StopIteration: - break - - return paged_return - - -def create_object_model(module_name, object_name, **kwargs): - """ - Assemble an object from incoming parameters. - """ - object_kwargs = {} - - try: - model_module = importlib.import_module( - "azure.mgmt.{}.models".format(module_name) - ) - # pylint: disable=invalid-name - Model = getattr(model_module, object_name) - except ImportError: - raise sys.exit( - "The {} model in the {} Azure module is not available.".format( - object_name, module_name - ) - ) - - if "_attribute_map" in dir(Model): - for attr, items in Model._attribute_map.items(): - param = kwargs.get(attr) - if param is not None: - if items["type"][0].isupper() and isinstance(param, dict): - object_kwargs[attr] = create_object_model( - module_name, items["type"], **param - ) - elif items["type"][0] == "{" and isinstance(param, dict): - object_kwargs[attr] = param - elif items["type"][0] == "[" and isinstance(param, list): - obj_list = [] - for list_item in param: - if items["type"][1].isupper() and isinstance(list_item, dict): - obj_list.append( - create_object_model( - module_name, - items["type"][ - items["type"].index("[") - + 1 : items["type"].rindex("]") - ], - **list_item - ) - ) - elif items["type"][1] == "{" and isinstance(list_item, dict): - obj_list.append(list_item) - elif not items["type"][1].isupper() and items["type"][1] != "{": - obj_list.append(list_item) - object_kwargs[attr] = obj_list - else: - object_kwargs[attr] = param - - # wrap calls to this function to catch TypeError exceptions - return Model(**object_kwargs) - - -def compare_list_of_dicts(old, new, convert_id_to_name=None): - """ - Compare lists of dictionaries representing Azure objects. Only keys found in the "new" dictionaries are compared to - the "old" dictionaries, since getting Azure objects from the API returns some read-only data which should not be - used in the comparison. A list of parameter names can be passed in order to compare a bare object name to a full - Azure ID path for brevity. If string types are found in values, comparison is case insensitive. Return comment - should be used to trigger exit from the calling function. - """ - ret = {} - - if not convert_id_to_name: - convert_id_to_name = [] - - if not isinstance(new, list): - ret["comment"] = "must be provided as a list of dictionaries!" - return ret - - if len(new) != len(old): - ret["changes"] = {"old": old, "new": new} - return ret - - try: - local_configs, remote_configs = ( - sorted(config, key=itemgetter("name")) for config in (new, old) - ) - except TypeError: - ret["comment"] = "configurations must be provided as a list of dictionaries!" - return ret - except KeyError: - ret["comment"] = 'configuration dictionaries must contain the "name" key!' - return ret - - for idx, val in enumerate(local_configs): - for key in val: - local_val = val[key] - if key in convert_id_to_name: - remote_val = ( - remote_configs[idx].get(key, {}).get("id", "").split("/")[-1] - ) - else: - remote_val = remote_configs[idx].get(key) - if isinstance(local_val, str): - local_val = local_val.lower() - if isinstance(remote_val, str): - remote_val = remote_val.lower() - if local_val != remote_val: - ret["changes"] = {"old": remote_configs, "new": local_configs} - return ret - - return ret diff --git a/salt/utils/msazure.py b/salt/utils/msazure.py deleted file mode 100644 index 28f8f33cc2f..00000000000 --- a/salt/utils/msazure.py +++ /dev/null @@ -1,189 +0,0 @@ -""" -.. versionadded:: 2015.8.0 - -Utilities for accessing storage container blobs on Azure -""" - - -import logging - -from salt.exceptions import SaltSystemExit - -HAS_LIBS = False -try: - import azure - - HAS_LIBS = True -except ImportError: - pass - - -log = logging.getLogger(__name__) - - -def get_storage_conn(storage_account=None, storage_key=None, opts=None): - """ - .. versionadded:: 2015.8.0 - - Return a storage_conn object for the storage account - """ - if opts is None: - opts = {} - - if not storage_account: - storage_account = opts.get("storage_account", None) - if not storage_key: - storage_key = opts.get("storage_key", None) - - return azure.storage.BlobService(storage_account, storage_key) - - -def list_blobs(storage_conn=None, **kwargs): - """ - .. versionadded:: 2015.8.0 - - List blobs associated with the container - """ - if not storage_conn: - storage_conn = get_storage_conn(opts=kwargs) - - if "container" not in kwargs: - raise SaltSystemExit( - code=42, msg='An storage container name must be specified as "container"' - ) - - data = storage_conn.list_blobs( - container_name=kwargs["container"], - prefix=kwargs.get("prefix", None), - marker=kwargs.get("marker", None), - maxresults=kwargs.get("maxresults", None), - include=kwargs.get("include", None), - delimiter=kwargs.get("delimiter", None), - ) - - ret = {} - for item in data.blobs: - ret[item.name] = object_to_dict(item) - return ret - - -def put_blob(storage_conn=None, **kwargs): - """ - .. versionadded:: 2015.8.0 - - Upload a blob - """ - if not storage_conn: - storage_conn = get_storage_conn(opts=kwargs) - - if "container" not in kwargs: - raise SaltSystemExit( - code=42, msg='The blob container name must be specified as "container"' - ) - - if "name" not in kwargs: - raise SaltSystemExit(code=42, msg='The blob name must be specified as "name"') - - if "blob_path" not in kwargs and "blob_content" not in kwargs: - raise SaltSystemExit( - code=42, - msg=( - 'Either a path to a file needs to be passed in as "blob_path" ' - 'or the contents of a blob as "blob_content."' - ), - ) - - blob_kwargs = { - "container_name": kwargs["container"], - "blob_name": kwargs["name"], - "cache_control": kwargs.get("cache_control", None), - "content_language": kwargs.get("content_language", None), - "content_md5": kwargs.get("content_md5", None), - "x_ms_blob_content_type": kwargs.get("blob_content_type", None), - "x_ms_blob_content_encoding": kwargs.get("blob_content_encoding", None), - "x_ms_blob_content_language": kwargs.get("blob_content_language", None), - "x_ms_blob_content_md5": kwargs.get("blob_content_md5", None), - "x_ms_blob_cache_control": kwargs.get("blob_cache_control", None), - "x_ms_meta_name_values": kwargs.get("meta_name_values", None), - "x_ms_lease_id": kwargs.get("lease_id", None), - } - if "blob_path" in kwargs: - data = storage_conn.put_block_blob_from_path( - file_path=kwargs["blob_path"], **blob_kwargs - ) - elif "blob_content" in kwargs: - data = storage_conn.put_block_blob_from_bytes( - blob=kwargs["blob_content"], **blob_kwargs - ) - - return data - - -def get_blob(storage_conn=None, **kwargs): - """ - .. versionadded:: 2015.8.0 - - Download a blob - """ - if not storage_conn: - storage_conn = get_storage_conn(opts=kwargs) - - if "container" not in kwargs: - raise SaltSystemExit( - code=42, msg='The blob container name must be specified as "container"' - ) - - if "name" not in kwargs: - raise SaltSystemExit(code=42, msg='The blob name must be specified as "name"') - - if "local_path" not in kwargs and "return_content" not in kwargs: - raise SaltSystemExit( - code=42, - msg=( - 'Either a local path needs to be passed in as "local_path", ' - 'or "return_content" to return the blob contents directly' - ), - ) - - blob_kwargs = { - "container_name": kwargs["container"], - "blob_name": kwargs["name"], - "snapshot": kwargs.get("snapshot", None), - "x_ms_lease_id": kwargs.get("lease_id", None), - "progress_callback": kwargs.get("progress_callback", None), - "max_connections": kwargs.get("max_connections", 1), - "max_retries": kwargs.get("max_retries", 5), - "retry_wait": kwargs.get("retry_wait", 1), - } - - if "local_path" in kwargs: - data = storage_conn.get_blob_to_path( - file_path=kwargs["local_path"], - open_mode=kwargs.get("open_mode", "wb"), - **blob_kwargs - ) - elif "return_content" in kwargs: - data = storage_conn.get_blob_to_bytes(**blob_kwargs) - - return data - - -def object_to_dict(obj): - """ - .. versionadded:: 2015.8.0 - - Convert an object to a dictionary - """ - if isinstance(obj, list) or isinstance(obj, tuple): - ret = [] - for item in obj: - ret.append(object_to_dict(item)) - elif hasattr(obj, "__dict__"): - ret = {} - for item in obj.__dict__: - if item.startswith("_"): - continue - ret[item] = object_to_dict(obj.__dict__[item]) - else: - ret = obj - return ret diff --git a/tests/integration/cloud/clouds/test_msazure.py b/tests/integration/cloud/clouds/test_msazure.py deleted file mode 100644 index 1439d4195d2..00000000000 --- a/tests/integration/cloud/clouds/test_msazure.py +++ /dev/null @@ -1,66 +0,0 @@ -""" - :codeauthor: Nicole Thomas -""" - -import logging - -import pytest - -from salt.utils.versions import Version -from tests.integration.cloud.helpers.cloud_test_base import CloudTest - -try: - import azure # pylint: disable=unused-import - - HAS_AZURE = True -except ImportError: - HAS_AZURE = False - -if HAS_AZURE and not hasattr(azure, "__version__"): - import azure.common - -log = logging.getLogger(__name__) - -TIMEOUT = 1000 -REQUIRED_AZURE = "1.1.0" - - -def __has_required_azure(): - """ - Returns True/False if the required version of the Azure SDK is installed. - """ - if HAS_AZURE: - if hasattr(azure, "__version__"): - version = Version(azure.__version__) - else: - version = Version(azure.common.__version__) - if Version(REQUIRED_AZURE) <= version: - return True - return False - - -@pytest.mark.skipif( - not HAS_AZURE, reason="These tests require the Azure Python SDK to be installed." -) -@pytest.mark.skipif( - not __has_required_azure(), - reason="The Azure Python SDK must be >= {}.".format(REQUIRED_AZURE), -) -class AzureTest(CloudTest): - """ - Integration tests for the Azure cloud provider in Salt-Cloud - """ - - PROVIDER = "azurearm" - REQUIRED_PROVIDER_CONFIG_ITEMS = ("subscription_id",) - - def test_instance(self): - """ - Test creating an instance on Azure - """ - # check if instance with salt installed returned - ret_val = self.run_cloud( - "-p azure-test {}".format(self.instance_name), timeout=TIMEOUT - ) - self.assertInstanceExists(ret_val) - self.assertDestroyInstance(timeout=TIMEOUT) diff --git a/tests/integration/files/conf/cloud.profiles.d/azure.conf b/tests/integration/files/conf/cloud.profiles.d/azure.conf deleted file mode 100644 index bfc749cc9e5..00000000000 --- a/tests/integration/files/conf/cloud.profiles.d/azure.conf +++ /dev/null @@ -1,8 +0,0 @@ -azure-test: - provider: azurearm-config - image: 'b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04-LTS-amd64-server-20140724-en-us-30GB' - size: Standard_D1 - slot: production - ssh_username: '' - ssh_password: '' - script_args: '-P' diff --git a/tests/integration/files/conf/cloud.providers.d/azurearm.conf b/tests/integration/files/conf/cloud.providers.d/azurearm.conf deleted file mode 100644 index 60c34667c1e..00000000000 --- a/tests/integration/files/conf/cloud.providers.d/azurearm.conf +++ /dev/null @@ -1,16 +0,0 @@ -azurearm-config: - driver: azurearm - subscription_id: '' - cleanup_disks: True - cleanup_interfaces: True - cleanup_vhds: True - cleanup_services: True - minion: - master_type: str - username: '' - password: '' - location: '' - network_resource_group: '' - network: '' - subnet: '' - resource_group: '' diff --git a/tests/pytests/unit/cloud/clouds/test_azurearm.py b/tests/pytests/unit/cloud/clouds/test_azurearm.py deleted file mode 100644 index d84aeeffd65..00000000000 --- a/tests/pytests/unit/cloud/clouds/test_azurearm.py +++ /dev/null @@ -1,161 +0,0 @@ -import types - -import pytest - -from salt.cloud.clouds import azurearm as azure -from tests.support.mock import MagicMock, create_autospec, patch - - -def copy_func(func, globals=None): - # I do not know that this is complete, but it's sufficient for now. - # The key to "moving" the function to another module (or stubbed module) - # is to update __globals__. - - copied_func = types.FunctionType( - func.__code__, globals, func.__name__, func.__defaults__, func.__closure__ - ) - copied_func.__module__ = func.__module__ - copied_func.__doc__ = func.__doc__ - copied_func.__kwdefaults__ = func.__kwdefaults__ - copied_func.__dict__.update(func.__dict__) - return copied_func - - -def mock_module(mod, sut=None): - if sut is None: - sut = [None] - - mock = create_autospec(mod) - - # we need to provide a '__globals__' so functions being tested behave correctly. - mock_globals = {} - - # exclude the system under test - for name in sut: - attr = getattr(mod, name) - if isinstance(attr, types.FunctionType): - attr = copy_func(attr, mock_globals) - setattr(mock, name, attr) - - # fully populate our mock_globals - for name in mod.__dict__: - if name in mock.__dict__: - mock_globals[name] = mock.__dict__[name] - elif type(getattr(mod, name)) is type(types): # is a module - mock_globals[name] = getattr(mock, name) - else: - mock_globals[name] = mod.__dict__[name] - - return mock - - -@pytest.fixture -def configure_loader_modules(): - return {azure: {"__opts__": {}, "__active_provider_name__": None}} - - -@pytest.mark.skipif(not azure.HAS_LIBS, reason="azure not available") -def test_function_signatures(): - mock_azure = mock_module(azure, sut=["request_instance", "__opts__", "__utils__"]) - mock_azure.create_network_interface.return_value = [ - MagicMock(), - MagicMock(), - MagicMock(), - ] - mock_azure.salt.utils.stringutils.to_str.return_value = "P4ssw0rd" - mock_azure.salt.utils.cloud.gen_keys.return_value = [MagicMock(), MagicMock()] - mock_azure.__opts__["pki_dir"] = None - - mock_azure.request_instance.__globals__[ - "__builtins__" - ] = mock_azure.request_instance.__globals__["__builtins__"].copy() - mock_azure.request_instance.__globals__["__builtins__"]["getattr"] = MagicMock() - - mock_azure.__utils__["cloud.fire_event"] = mock_azure.salt.utils.cloud.fire_event - mock_azure.__utils__[ - "cloud.filter_event" - ] = mock_azure.salt.utils.cloud.filter_event - mock_azure.__opts__["sock_dir"] = MagicMock() - mock_azure.__opts__["transport"] = MagicMock() - - mock_azure.request_instance( - {"image": "http://img", "storage_account": "blah", "size": ""} - ) - - # we literally only check that a final creation call occurred. - mock_azure.get_conn.return_value.virtual_machines.create_or_update.assert_called_once() - - -def test_get_configured_provider(): - mock_azure = mock_module( - azure, sut=["get_configured_provider", "__opts__", "__utils__"] - ) - - good_combos = [ - { - "subscription_id": "3287abc8-f98a-c678-3bde-326766fd3617", - "tenant": "ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF", - "client_id": "ABCDEFAB-1234-ABCD-1234-ABCDEFABCDEF", - "secret": "XXXXXXXXXXXXXXXXXXXXXXXX", - }, - { - "subscription_id": "3287abc8-f98a-c678-3bde-326766fd3617", - "username": "larry", - "password": "123pass", - }, - {"subscription_id": "3287abc8-f98a-c678-3bde-326766fd3617"}, - ] - - for combo in good_combos: - mock_azure.__opts__["providers"] = {"azure_test": {"azurearm": combo}} - assert azure.get_configured_provider() == combo - - bad_combos = [ - {"subscrption": "3287abc8-f98a-c678-3bde-326766fd3617"}, - {}, - ] - - for combo in bad_combos: - mock_azure.__opts__["providers"] = {"azure_test": {"azurearm": combo}} - assert not azure.get_configured_provider() - - -def test_get_conn(): - mock_azure = mock_module(azure, sut=["get_conn", "__opts__", "__utils__"]) - - mock_azure.__opts__["providers"] = { - "azure_test": { - "azurearm": { - "subscription_id": "3287abc8-f98a-c678-3bde-326766fd3617", - "driver": "azurearm", - "password": "monkeydonkey", - } - } - } - # password is stripped if username not provided - expected = {"subscription_id": "3287abc8-f98a-c678-3bde-326766fd3617"} - with patch( - "salt.utils.azurearm.get_client", side_effect=lambda client_type, **kw: kw - ): - assert azure.get_conn(client_type="compute") == expected - - mock_azure.__opts__["providers"] = { - "azure_test": { - "azurearm": { - "subscription_id": "3287abc8-f98a-c678-3bde-326766fd3617", - "driver": "azurearm", - "username": "donkeymonkey", - "password": "monkeydonkey", - } - } - } - # username and password via provider config - expected = { - "subscription_id": "3287abc8-f98a-c678-3bde-326766fd3617", - "username": "donkeymonkey", - "password": "monkeydonkey", - } - with patch( - "salt.utils.azurearm.get_client", side_effect=lambda client_type, **kw: kw - ): - assert azure.get_conn(client_type="compute") == expected diff --git a/tests/pytests/unit/grains/test_metadata_azure.py b/tests/pytests/unit/grains/test_metadata_azure.py deleted file mode 100644 index 4f9bc9988a7..00000000000 --- a/tests/pytests/unit/grains/test_metadata_azure.py +++ /dev/null @@ -1,96 +0,0 @@ -""" - Unit test for salt.grains.metadata_azure - - - :codeauthor: :email" `Vishal Gupta - -""" - -import logging - -import pytest - -import salt.grains.metadata_azure as metadata -import salt.utils.http as http -from tests.support.mock import create_autospec, patch - -# from Exception import Exception, ValueError - -log = logging.getLogger(__name__) - - -@pytest.fixture -def configure_loader_modules(): - return {metadata: {"__opts__": {"metadata_server_grains": "True"}}} - - -def test_metadata_azure_search(): - def mock_http(url="", headers=False, header_list=None): - metadata_vals = { - "http://169.254.169.254/metadata/instance?api-version=2020-09-01": { - "body": '{"compute": {"test": "fulltest"}}', - "headers": {"Content-Type": "application/json; charset=utf-8"}, - }, - } - - return metadata_vals[url] - - with patch( - "salt.utils.http.query", - create_autospec(http.query, autospec=True, side_effect=mock_http), - ): - assert metadata.metadata() == {"compute": {"test": "fulltest"}} - - -def test_metadata_virtual(): - print("running 1st") - with patch( - "salt.utils.http.query", - create_autospec( - http.query, - autospec=True, - return_value={ - "error": "Bad request: . Required metadata header not specified" - }, - ), - ): - assert metadata.__virtual__() is False - with patch( - "salt.utils.http.query", - create_autospec( - http.query, - autospec=True, - return_value={ - "body": '{"compute": {"test": "fulltest"}}', - "headers": {"Content-Type": "application/json; charset=utf-8"}, - "status": 200, - }, - ), - ): - assert metadata.__virtual__() is True - with patch( - "salt.utils.http.query", - create_autospec( - http.query, - autospec=True, - return_value={ - "body": "test", - "headers": {"Content-Type": "application/json; charset=utf-8"}, - "status": 404, - }, - ), - ): - assert metadata.__virtual__() is False - with patch( - "salt.utils.http.query", - create_autospec( - http.query, - autospec=True, - return_value={ - "body": "test", - "headers": {"Content-Type": "application/json; charset=utf-8"}, - "status": 400, - }, - ), - ): - assert metadata.__virtual__() is False diff --git a/tests/pytests/unit/modules/test_azurearm_dns.py b/tests/pytests/unit/modules/test_azurearm_dns.py deleted file mode 100644 index 3c09e23143f..00000000000 --- a/tests/pytests/unit/modules/test_azurearm_dns.py +++ /dev/null @@ -1,182 +0,0 @@ -import logging - -import pytest - -import salt.config -import salt.loader -import salt.modules.azurearm_dns as azurearm_dns -from tests.support.mock import MagicMock -from tests.support.sminion import create_sminion - -HAS_LIBS = False -try: - import azure.mgmt.dns.models # pylint: disable=import-error - - HAS_LIBS = True -except ImportError: - HAS_LIBS = False - - -log = logging.getLogger(__name__) - -pytestmark = [ - pytest.mark.skipif( - HAS_LIBS is False, reason="The azure.mgmt.dns module must be installed." - ), -] - - -class AzureObjMock: - """ - mock azure object for as_dict calls - """ - - args = None - kwargs = None - - def __init__(self, args, kwargs, return_value=None): - self.args = args - self.kwargs = kwargs - self.__return_value = return_value - - def __getattr__(self, item): - return self - - def __call__(self, *args, **kwargs): - return MagicMock(return_value=self.__return_value)() - - def as_dict(self, *args, **kwargs): - return self.args, self.kwargs - - -class AzureFuncMock: - """ - mock azure client function calls - """ - - def __init__(self, return_value=None): - self.__return_value = return_value - - def __getattr__(self, item): - return self - - def __call__(self, *args, **kwargs): - return MagicMock(return_value=self.__return_value)() - - def create_or_update(self, *args, **kwargs): - azure_obj = AzureObjMock(args, kwargs) - return azure_obj - - -class AzureSubMock: - """ - mock azure client sub-modules - """ - - record_sets = AzureFuncMock() - zones = AzureFuncMock() - - def __init__(self, return_value=None): - self.__return_value = return_value - - def __getattr__(self, item): - return self - - def __call__(self, *args, **kwargs): - return MagicMock(return_value=self.__return_value)() - - -class AzureClientMock: - """ - mock azure client - """ - - def __init__(self, return_value=AzureSubMock): - self.__return_value = return_value - - def __getattr__(self, item): - return self - - def __call__(self, *args, **kwargs): - return MagicMock(return_value=self.__return_value)() - - -@pytest.fixture -def credentials(): - azurearm_dns.__virtual__() - return { - "client_id": "CLIENT_ID", - "secret": "SECRET", - "subscription_id": "SUBSCRIPTION_ID", - "tenant": "TENANT", - } - - -@pytest.fixture -def configure_loader_modules(): - """ - setup loader modules and override the azurearm.get_client utility - """ - minion_config = create_sminion().opts.copy() - utils = salt.loader.utils(minion_config) - funcs = salt.loader.minion_mods( - minion_config, utils=utils, whitelist=["azurearm_dns", "config"] - ) - utils["azurearm.get_client"] = AzureClientMock() - return { - azurearm_dns: {"__utils__": utils, "__salt__": funcs}, - } - - -def test_record_set_create_or_update(credentials): - """ - tests record set object creation - """ - expected = { - "if_match": None, - "if_none_match": None, - "parameters": {"arecords": [{"ipv4_address": "10.0.0.1"}], "ttl": 300}, - "record_type": "A", - "relative_record_set_name": "myhost", - "resource_group_name": "testgroup", - "zone_name": "myzone", - } - - record_set_args, record_set_kwargs = azurearm_dns.record_set_create_or_update( - "myhost", - "myzone", - "testgroup", - "A", - arecords=[{"ipv4_address": "10.0.0.1"}], - ttl=300, - **credentials - ) - - for key, val in record_set_kwargs.items(): - if isinstance(val, azure.mgmt.dns.models.RecordSet): - record_set_kwargs[key] = val.as_dict() - - assert record_set_kwargs == expected - - -def test_zone_create_or_update(credentials): - """ - tests zone object creation - """ - expected = { - "if_match": None, - "if_none_match": None, - "parameters": {"location": "global", "zone_type": "Public"}, - "resource_group_name": "testgroup", - "zone_name": "myzone", - } - - zone_args, zone_kwargs = azurearm_dns.zone_create_or_update( - "myzone", "testgroup", **credentials - ) - - for key, val in zone_kwargs.items(): - if isinstance(val, azure.mgmt.dns.models.Zone): - zone_kwargs[key] = val.as_dict() - - assert zone_kwargs == expected diff --git a/tests/pytests/unit/pillar/test_azureblob.py b/tests/pytests/unit/pillar/test_azureblob.py deleted file mode 100644 index b152f614bdc..00000000000 --- a/tests/pytests/unit/pillar/test_azureblob.py +++ /dev/null @@ -1,333 +0,0 @@ -""" -Tests for the Azure Blob External Pillar. -""" - -import pickle -import time - -import pytest - -import salt.config -import salt.loader -import salt.pillar.azureblob as azureblob -import salt.utils.files -from tests.support.mock import MagicMock, patch - -HAS_LIBS = False -try: - # pylint: disable=no-name-in-module - from azure.storage.blob import BlobServiceClient - - # pylint: enable=no-name-in-module - - HAS_LIBS = True -except ImportError: - pass - - -pytestmark = [ - pytest.mark.skipif( - HAS_LIBS is False, - reason="The azure.storage.blob module must be installed.", - ) -] - - -class MockBlob(dict): - """ - Creates a Mock Blob object. - """ - - name = "" - - def __init__(self): - super().__init__( - { - "container": None, - "name": "test.sls", - "prefix": None, - "delimiter": "/", - "results_per_page": None, - "location_mode": None, - } - ) - - -class MockContainerClient: - """ - Creates a Mock ContainerClient. - """ - - def __init__(self): - pass - - def walk_blobs(self, *args, **kwargs): - yield MockBlob() - - def get_blob_client(self, *args, **kwargs): - pass - - -class MockBlobServiceClient: - """ - Creates a Mock BlobServiceClient. - """ - - def __init__(self): - pass - - def get_container_client(self, *args, **kwargs): - container_client = MockContainerClient() - return container_client - - -@pytest.fixture -def cachedir(tmp_path): - dirname = tmp_path / "cachedir" - dirname.mkdir(parents=True, exist_ok=True) - return dirname - - -@pytest.fixture -def configure_loader_modules(cachedir, tmp_path): - base_pillar = tmp_path / "base" - prod_pillar = tmp_path / "prod" - base_pillar.mkdir(parents=True, exist_ok=True) - prod_pillar.mkdir(parents=True, exist_ok=True) - pillar_roots = { - "base": [str(base_pillar)], - "prod": [str(prod_pillar)], - } - opts = { - "cachedir": cachedir, - "pillar_roots": pillar_roots, - } - return { - azureblob: {"__opts__": opts}, - } - - -def test__init_expired(tmp_path): - """ - Tests the result of _init when the cache is expired. - """ - container = "test" - multiple_env = False - environment = "base" - blob_cache_expire = 0 # The cache will be expired - blob_client = MockBlobServiceClient() - cache_file = tmp_path / "cache_file" - # Patches the _get_containers_cache_filename module so that it returns the name of the new tempfile that - # represents the cache file - with patch.object( - azureblob, - "_get_containers_cache_filename", - MagicMock(return_value=str(cache_file)), - ): - # Patches the from_connection_string module of the BlobServiceClient class so that a connection string does - # not need to be given. Additionally it returns example blob data used by the ext_pillar. - with patch.object( - BlobServiceClient, - "from_connection_string", - MagicMock(return_value=blob_client), - ): - ret = azureblob._init( - "", container, multiple_env, environment, blob_cache_expire - ) - - expected = { - "base": { - "test": [ - { - "container": None, - "name": "test.sls", - "prefix": None, - "delimiter": "/", - "results_per_page": None, - "location_mode": None, - } - ] - } - } - assert ret == expected - - -def test__init_not_expired(tmp_path): - """ - Tests the result of _init when the cache is not expired. - """ - container = "test" - multiple_env = False - environment = "base" - blob_cache_expire = (time.time()) * (time.time()) # The cache will not be expired - metadata = { - "base": { - "test": [ - {"name": "base/secret.sls", "relevant": "include.sls"}, - {"name": "blobtest.sls", "irrelevant": "ignore.sls"}, - ] - } - } - cache_file = tmp_path / "cache_file" - # Pickles the metadata and stores it in cache_file - with salt.utils.files.fopen(str(cache_file), "wb") as fp_: - pickle.dump(metadata, fp_) - # Patches the _get_containers_cache_filename module so that it returns the name of the new tempfile that - # represents the cache file - with patch.object( - azureblob, - "_get_containers_cache_filename", - MagicMock(return_value=str(cache_file)), - ): - # Patches the _read_containers_cache_file module so that it returns what it normally would if the new - # tempfile representing the cache file was passed to it - plugged = azureblob._read_containers_cache_file(str(cache_file)) - with patch.object( - azureblob, - "_read_containers_cache_file", - MagicMock(return_value=plugged), - ): - ret = azureblob._init( - "", container, multiple_env, environment, blob_cache_expire - ) - assert ret == metadata - - -def test__get_cache_dir(cachedir): - """ - Tests the result of _get_cache_dir. - """ - ret = azureblob._get_cache_dir() - assert ret == str(cachedir / "pillar_azureblob") - - -def test__get_cached_file_name(cachedir): - """ - Tests the result of _get_cached_file_name. - """ - container = "test" - saltenv = "base" - path = "base/secret.sls" - ret = azureblob._get_cached_file_name(container, saltenv, path) - assert ret == str(cachedir / "pillar_azureblob" / saltenv / container / path) - - -def test__get_containers_cache_filename(cachedir): - """ - Tests the result of _get_containers_cache_filename. - """ - container = "test" - ret = azureblob._get_containers_cache_filename(container) - assert ret == str(cachedir / "pillar_azureblob" / "test-files.cache") - - -def test__refresh_containers_cache_file(tmp_path): - """ - Tests the result of _refresh_containers_cache_file to ensure that it successfully copies blob data into a - cache file. - """ - blob_client = MockBlobServiceClient() - container = "test" - cache_file = tmp_path / "cache_file" - with patch.object( - BlobServiceClient, - "from_connection_string", - MagicMock(return_value=blob_client), - ): - ret = azureblob._refresh_containers_cache_file("", container, str(cache_file)) - expected = { - "base": { - "test": [ - { - "container": None, - "name": "test.sls", - "prefix": None, - "delimiter": "/", - "results_per_page": None, - "location_mode": None, - } - ] - } - } - assert ret == expected - - -def test__read_containers_cache_file(tmp_path): - """ - Tests the result of _read_containers_cache_file to make sure that it successfully loads in pickled metadata. - """ - metadata = { - "base": { - "test": [ - {"name": "base/secret.sls", "relevant": "include.sls"}, - {"name": "blobtest.sls", "irrelevant": "ignore.sls"}, - ] - } - } - cache_file = tmp_path / "cache_file" - # Pickles the metadata and stores it in cache_file - with salt.utils.files.fopen(str(cache_file), "wb") as fp_: - pickle.dump(metadata, fp_) - # Checks to see if _read_containers_cache_file can successfully read the pickled metadata from the cache file - ret = azureblob._read_containers_cache_file(str(cache_file)) - assert ret == metadata - - -def test__find_files(): - """ - Tests the result of _find_files. Ensures it only finds files and not directories. Ensures it also ignore - irrelevant files. - """ - metadata = { - "test": [ - {"name": "base/secret.sls"}, - {"name": "blobtest.sls", "irrelevant": "ignore.sls"}, - {"name": "base/"}, - ] - } - ret = azureblob._find_files(metadata) - assert ret == {"test": ["base/secret.sls", "blobtest.sls"]} - - -def test__find_file_meta1(): - """ - Tests the result of _find_file_meta when the metadata contains a blob with the specified path and a blob - without the specified path. - """ - metadata = { - "base": { - "test": [ - {"name": "base/secret.sls", "relevant": "include.sls"}, - {"name": "blobtest.sls", "irrelevant": "ignore.sls"}, - ] - } - } - container = "test" - saltenv = "base" - path = "base/secret.sls" - ret = azureblob._find_file_meta(metadata, container, saltenv, path) - assert ret == {"name": "base/secret.sls", "relevant": "include.sls"} - - -def test__find_file_meta2(): - """ - Tests the result of _find_file_meta when the saltenv in metadata does not match the specified saltenv. - """ - metadata = {"wrong": {"test": [{"name": "base/secret.sls"}]}} - container = "test" - saltenv = "base" - path = "base/secret.sls" - ret = azureblob._find_file_meta(metadata, container, saltenv, path) - assert ret is None - - -def test__find_file_meta3(): - """ - Tests the result of _find_file_meta when the container in metadata does not match the specified metadata. - """ - metadata = {"base": {"wrong": [{"name": "base/secret.sls"}]}} - container = "test" - saltenv = "base" - path = "base/secret.sls" - ret = azureblob._find_file_meta(metadata, container, saltenv, path) - assert ret is None diff --git a/tests/unit/utils/test_azurearm.py b/tests/unit/utils/test_azurearm.py deleted file mode 100644 index 6bfab788fae..00000000000 --- a/tests/unit/utils/test_azurearm.py +++ /dev/null @@ -1,55 +0,0 @@ -import logging - -import pytest - -import salt.utils.azurearm as azurearm -from tests.support.unit import TestCase - -# Azure libs -# pylint: disable=import-error -HAS_LIBS = False -try: - import azure.mgmt.compute.models # pylint: disable=unused-import - import azure.mgmt.network.models # pylint: disable=unused-import - - HAS_LIBS = True -except ImportError: - pass - -# pylint: enable=import-error - -log = logging.getLogger(__name__) - -MOCK_CREDENTIALS = { - "client_id": "CLIENT_ID", - "secret": "SECRET", - "subscription_id": "SUBSCRIPTION_ID", - "tenant": "TENANT", -} - - -@pytest.mark.skipif( - HAS_LIBS is False, reason="The azure.mgmt.network module must be installed." -) -class AzureRmUtilsTestCase(TestCase): - def test_create_object_model_vnet(self): - module_name = "network" - object_name = "VirtualNetwork" - vnet = { - "address_space": {"address_prefixes": ["10.0.0.0/8"]}, - "enable_ddos_protection": False, - "enable_vm_protection": True, - "tags": {"contact_name": "Elmer Fudd Gantry"}, - } - model = azurearm.create_object_model(module_name, object_name, **vnet) - self.assertEqual(vnet, model.as_dict()) - - def test_create_object_model_nic_ref(self): - module_name = "compute" - object_name = "NetworkInterfaceReference" - ref = { - "id": "/subscriptions/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa/resourceGroups/rg/providers/Microsoft.Network/networkInterfaces/nic", - "primary": False, - } - model = azurearm.create_object_model(module_name, object_name, **ref) - self.assertEqual(ref, model.as_dict())