diff --git a/requirements.txt b/requirements.txt
index 6ff5f2e9d..552e92c78 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -50,3 +50,7 @@ boto3==1.20.*
 botocore==1.23.*
 urllib3==1.26.*
 Werkzeug==2.0.3
+azure-mgmt-rdbms==10.1.0
+azure-mgmt-resource==21.0.0
+azure-mgmt-subscription==3.0.0
+azure-identity==1.9.0
diff --git a/web/pgacloud/providers/azure.py b/web/pgacloud/providers/azure.py
new file mode 100644
index 000000000..fcbbdde46
--- /dev/null
+++ b/web/pgacloud/providers/azure.py
@@ -0,0 +1,332 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2022, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+""" Azure PostgreSQL provider """
+
+from azure.mgmt.rdbms.postgresql_flexibleservers import \
+    PostgreSQLManagementClient
+from azure.mgmt.rdbms.postgresql_flexibleservers.models import Sku, SkuTier, \
+    CreateMode, Storage, Server, FirewallRule
+from azure.identity import AzureCliCredential, InteractiveBrowserCredential, \
+    AuthenticationRecord, TokenCachePersistenceOptions
+from azure.mgmt.resource import ResourceManagementClient
+from azure.core.exceptions import ResourceNotFoundError
+from providers._abstract import AbsProvider
+import os
+from utils.io import debug, error, output
+from utils.misc import get_my_ip, get_random_id
+
+
+class AzureProvider(AbsProvider):
+    def __init__(self):
+        self._clients = {}
+        self._tenant_id = None
+        self._client_id = None
+        self._client_secret = None
+        self._subscription_id = None
+        self._default_region = None
+        self._use_interactive_browser_credential = False
+        self._available_capabilities = None
+        self._credentials = None
+        self._authentication_record_json = None
+        self._cli_credentials = None
+
+        # Get the credentials
+        if 'AUTHENTICATION_RECORD_JSON' in os.environ:
+            self._authentication_record_json = os.environ[
+                'AUTHENTICATION_RECORD_JSON']
+
+        if 'AZURE_SUBSCRIPTION_ID' in os.environ:
+            self._subscription_id = os.environ['AZURE_SUBSCRIPTION_ID']
+
+        if 'AZURE_TENANT_ID' in os.environ:
+            self._tenant_id = os.environ['AZURE_TENANT_ID']
+
+        if 'AUTH_TYPE' in os.environ:
+            self._use_interactive_browser_credential = False \
+                if os.environ['AUTH_TYPE'] == 'azure_cli_credential' else True
+
+    def init_args(self, parsers):
+        """ Create the command line parser for this provider """
+        self.parser = parsers. \
+            add_parser('azure',
+                       help='Azure Database for PostgreSQL',
+                       epilog='Credentials are read from '
+                              'the environment, '
+                              'specifically, the '
+                              'AZURE_SUBSCRIPTION_ID, '
+                              'AZURE_TENANT_ID, '
+                              'AZURE_CLIENT_ID and '
+                              'AZURE_CLIENT_SECRET '
+                              'variables. '
+                              'See https://docs.microsoft'
+                              '.com/en-us/azure/developer'
+                              '/python/configure-local'
+                              '-development-environment?tabs=cmd '
+                              'for more information.')
+
+        self.parser.add_argument('--region', default=self._default_region,
+                                 help='name of the Azure location (default: '
+                                      '{})'.format(self._default_region))
+
+        self.parser.add_argument('--resource-group', required=True,
+                                 help='name of the Azure resource group')
+
+        # Create the command sub-parser
+        parsers = self.parser.add_subparsers(help='Azure commands',
+                                             dest='command')
+
+        # Create the create instance command parser
+        parser_create_instance = parsers.add_parser('create-instance',
+                                                    help='create a new '
+                                                         'instance')
+
+        parser_create_instance.add_argument('--name', required=True,
+                                            help='name of the instance')
+        parser_create_instance.add_argument('--db-password', required=True,
+                                            help='password for the database')
+        parser_create_instance.add_argument('--db-username',
+                                            default='postgres',
+                                            help='user name for the database '
+                                                 '(default: postgres)')
+        parser_create_instance.add_argument('--db-major-version',
+                                            default='11',
+                                            help='version of PostgreSQL '
+                                                 'to deploy (default: 11)')
+        parser_create_instance.add_argument('--instance-type', required=True,
+                                            help='machine type for the '
+                                                 'instance nodes, e.g. '
+                                                 'GP_Gen5_8')
+        parser_create_instance.add_argument('--instance_tier_type',
+                                            required=True,
+                                            help='machine type for the '
+                                                 'instance nodes, e.g. '
+                                                 'GP_Gen5_8')
+        parser_create_instance.add_argument('--storage-size', type=int,
+                                            required=True,
+                                            help='storage size in GB')
+        parser_create_instance.add_argument('--availability-zone',
+                                            required=False,
+                                            help='Availability zone')
+        parser_create_instance.add_argument('--public-ips',
+                                            default='127.0.0.1',
+                                            help='Public IPs '
+                                                 '(default: 127.0.0.1)')
+
+        # Create the delete instance command parser
+        parser_delete_instance = parsers.add_parser('delete-instance',
+                                                    help='delete an instance')
+        parser_delete_instance.add_argument('--name', required=True,
+                                            help='name of the instance')
+
+    ##########################################################################
+    # Azure Helper functions
+    ##########################################################################
+    def _get_azure_credentials(self):
+        try:
+            if self._use_interactive_browser_credential:
+                if self._authentication_record_json is None:
+                    _credentials = self._azure_interactive_browser_credential()
+                    _auth_record_ = _credentials.authenticate()
+                    self._authentication_record_json = \
+                        _auth_record_.serialize()
+                else:
+                    deserialized_auth_record = AuthenticationRecord.\
+                        deserialize(self._authentication_record_json)
+                    _credentials = \
+                        self._azure_interactive_browser_credential(
+                            deserialized_auth_record)
+            else:
+                if self._cli_credentials is None:
+                    self._cli_credentials = AzureCliCredential()
+                _credentials = self._cli_credentials
+        except Exception as e:
+            return False, str(e)
+        return True, _credentials
+
+    def _azure_interactive_browser_credential(
+            self, deserialized_auth_record=None):
+        if deserialized_auth_record:
+            _credential = InteractiveBrowserCredential(
+                tenant_id=self._tenant_id,
+                timeout=180,
+                cache_persistence_options=TokenCachePersistenceOptions(),
+                authentication_record=deserialized_auth_record)
+        else:
+            _credential = InteractiveBrowserCredential(
+                tenant_id=self._tenant_id,
+                timeout=180,
+                cache_persistence_options=TokenCachePersistenceOptions())
+        return _credential
+
+    def _get_azure_client(self, type):
+        """ Create/cache/return an Azure client object """
+        # Acquire a credential object using CLI-based authentication.
+        if self._credentials is None:
+            status, self._credentials = \
+                self._get_azure_credentials()
+
+        if type in self._clients:
+            return self._clients[type]
+
+        if type == 'postgresql':
+            client = PostgreSQLManagementClient(self._credentials,
+                                                self._subscription_id)
+        elif type == 'resource':
+            client = ResourceManagementClient(self._credentials,
+                                              self._subscription_id)
+
+        self._clients[type] = client
+
+        return self._clients[type]
+
+    def _create_resource_group(self, args):
+        """ Create the Resource Group if it doesn't exist """
+        resource_client = self._get_azure_client('resource')
+
+        group_list = resource_client.resource_groups.list()
+        for group in list(group_list):
+            if group.name == args.resource_group:
+                debug('Resource group already exist with name: {}...'.format(
+                    args.resource_group))
+                return group.__dict__
+        debug(
+            'Creating resource group with name: {}...'.format(
+                args.resource_group))
+        result = resource_client.resource_groups.create_or_update(
+            args.resource_group,
+            {"location": args.region})
+        return result.__dict__
+
+    def _create_azure_instance(self, args):
+        """ Create an Azure instance """
+        # Obtain the management client object
+        postgresql_client = self._get_azure_client('postgresql')
+        # Check if the server already exists
+        svr = None
+        try:
+            svr = postgresql_client.servers.get(args.resource_group, args.name)
+        except ResourceNotFoundError:
+            pass
+        except Exception as e:
+            error(args, e)
+
+        if svr is not None:
+            error(args, 'Azure Database for PostgreSQL instance {} already '
+                        'exists.'.format(args.name))
+
+        # Provision the server and wait for the result
+        debug('Creating Azure instance: {}...'.format(args.name))
+
+        try:
+            poller = postgresql_client.servers.begin_create(
+                resource_group_name=args.resource_group,
+                server_name=args.name,
+                parameters=Server(
+
+                    sku=Sku(name=args.instance_type,
+                            tier=SkuTier(args.instance_tier_type)
+                            ),
+                    administrator_login=args.db_username,
+                    administrator_login_password=args.db_password,
+                    version=args.db_major_version,
+                    storage=Storage(
+                        storage_size_gb=args.storage_size
+                    ),
+                    location=args.region,
+                    create_mode=CreateMode("Default")
+                )
+            )
+        except Exception as e:
+            error(e)
+
+        server = poller.result()
+
+        return server.__dict__
+
+    def _create_firewall_rule(self, args):
+        """ Create a firewall rule on an instance """
+        firewall_rules = []
+        postgresql_client = self._get_azure_client('postgresql')
+        ip = args.public_ips if args.public_ips else get_my_ip()
+        ip_list = ip.split(',')
+        for ip in ip_list:
+            ip = ip.strip()
+            if '-' in ip:
+                start_ip = ip.split('-')[0]
+                end_ip = ip.split('-')[1]
+            else:
+                start_ip = ip
+                end_ip = ip
+            name = 'pgacloud_{}_{}_{}'.format(args.name,
+                                              ip.replace('.', '-'),
+                                              get_random_id())
+
+            # Provision the rule and wait for completion
+            debug('Adding ingress rule for: {0} - {1} ...'.format(start_ip,
+                                                                  end_ip))
+            poller = postgresql_client.firewall_rules.begin_create_or_update(
+                resource_group_name=args.resource_group,
+                server_name=args.name,
+                firewall_rule_name=name,
+                parameters=FirewallRule(start_ip_address=start_ip,
+                                        end_ip_address=end_ip)
+            )
+
+            firewall_rule = poller.result()
+
+            firewall_rules.append(firewall_rule.__dict__)
+        return firewall_rules
+
+    def _delete_azure_instance(self, args, name):
+        """ Delete an Azure instance """
+        # Obtain the management client object
+        postgresql_client = self._get_azure_client('postgresql')
+
+        # Delete the server and wait for the result
+        debug('Deleting Azure instance: {}...'.format(args.name))
+        try:
+            poller = postgresql_client.servers.begin_delete(
+                args.resource_group,
+                args.name
+            )
+        except Exception as e:
+            error(args, e)
+
+        poller.result()
+
+    ##########################################################################
+    # User commands
+    ##########################################################################
+    def cmd_create_instance(self, args):
+        """ Deploy an Azure instance and firewall rule """
+        rg = self._create_resource_group(args)
+        instance = self._create_azure_instance(args)
+        firewall_rules = self._create_firewall_rule(args)
+
+        data = {'instance': {
+            'Id': instance['id'],
+            'ResourceGroupId': rg['name'],
+            'Location': instance['location'],
+            'Hostname': instance['fully_qualified_domain_name'],
+            'Port': 5432,
+            'Database': "postgres",
+            'Username': instance['administrator_login']
+        }}
+
+        output(data)
+
+    def cmd_delete_instance(self, args):
+        """ Delete an Azure instance """
+        self._delete_azure_instance(args, args.name)
+
+
+def load():
+    """ Loads the current provider """
+    return AzureProvider()
diff --git a/web/pgadmin/misc/cloud/__init__.py b/web/pgadmin/misc/cloud/__init__.py
index 603e98dba..eff20bad9 100644
--- a/web/pgadmin/misc/cloud/__init__.py
+++ b/web/pgadmin/misc/cloud/__init__.py
@@ -26,6 +26,7 @@ from pgadmin.misc.cloud.utils import get_my_ip
 from pgadmin.misc.cloud.biganimal import deploy_on_biganimal,\
     clear_biganimal_session
 from pgadmin.misc.cloud.rds import deploy_on_rds, clear_aws_session
+from pgadmin.misc.cloud.azure import deploy_on_azure, clear_azure_session
 
 # set template path for sql scripts
 MODULE_NAME = 'cloud'
@@ -75,7 +76,8 @@ class CloudModule(PgAdminModule):
         return ['cloud.deploy_on_cloud',
                 'cloud.update_cloud_server',
                 'cloud.update_cloud_process',
-                'cloud.get_host_ip']
+                'cloud.get_host_ip',
+                'cloud.clear_cloud_session']
 
 
 # Create blueprint for CloudModule class
@@ -102,6 +104,15 @@ def script():
     return res
 
 
+@blueprint.route('/clear_cloud_session/',
+                 methods=['POST'], endpoint='clear_cloud_session')
+@login_required
+def clear_session():
+    """Get host IP Address"""
+    clear_cloud_session()
+    return make_json_response(success=1)
+
+
 @blueprint.route('/get_host_ip/',
                  methods=['GET'], endpoint='get_host_ip')
 @login_required
@@ -123,6 +134,8 @@ def deploy_on_cloud():
         status, resp = deploy_on_rds(data)
     elif data['cloud'] == 'biganimal':
         status, resp = deploy_on_biganimal(data)
+    elif data['cloud'] == 'azure':
+        status, resp = deploy_on_azure(data)
     else:
         status = False
         resp = gettext('No cloud implementation.')
@@ -188,7 +201,7 @@ def update_server(data):
         _server['status'] = False
     else:
         _server['status'] = True
-        clear_cloud_session()
+    clear_cloud_session()
 
     return True, _server
 
@@ -197,6 +210,7 @@ def clear_cloud_session():
     """Clear cloud sessions."""
     clear_aws_session()
     clear_biganimal_session()
+    clear_azure_session()
 
 
 @blueprint.route(
diff --git a/web/pgadmin/misc/cloud/azure/__init__.py b/web/pgadmin/misc/cloud/azure/__init__.py
new file mode 100644
index 000000000..810a65709
--- /dev/null
+++ b/web/pgadmin/misc/cloud/azure/__init__.py
@@ -0,0 +1,646 @@
+# ##########################################################################
+# #
+# # pgAdmin 4 - PostgreSQL Tools
+# #
+# # Copyright (C) 2013 - 2022, The pgAdmin Development Team
+# # This software is released under the PostgreSQL Licence
+# #
+# ##########################################################################
+
+# Azure implementation
+from pgadmin.misc.cloud.utils import _create_server, CloudProcessDesc
+from pgadmin.misc.bgprocess.processes import BatchProcess
+from pgadmin import make_json_response
+from pgadmin.utils import PgAdminModule
+from flask_security import login_required
+import simplejson as json
+from flask import session, current_app, request
+from config import root
+
+from azure.mgmt.rdbms.postgresql_flexibleservers import \
+    PostgreSQLManagementClient
+from azure.identity import AzureCliCredential, InteractiveBrowserCredential, \
+    TokenCachePersistenceOptions, AuthenticationRecord
+from azure.mgmt.resource import ResourceManagementClient
+from azure.mgmt.subscription import SubscriptionClient
+from azure.identity import AuthenticationRecord
+from azure.mgmt.rdbms.postgresql_flexibleservers.models import \
+    NameAvailabilityRequest
+
+MODULE_NAME = 'azure'
+
+
+class AzurePostgresqlModule(PgAdminModule):
+    """Cloud module to deploy on Azure Postgresql"""
+
+    def get_own_stylesheets(self):
+        """
+        Returns:
+            list: the stylesheets used by this module.
+        """
+        stylesheets = []
+        return stylesheets
+
+    def get_exposed_url_endpoints(self):
+        return ['azure.verify_credentials',
+                'azure.check_cluster_name_availability',
+                'azure.subscriptions',
+                'azure.resource_groups',
+                'azure.regions',
+                'azure.db_versions',
+                'azure.instance_types',
+                'azure.availability_zones',
+                'azure.storage_types']
+
+
+blueprint = AzurePostgresqlModule(MODULE_NAME, __name__,
+                                  static_url_path='/misc/cloud/azure')
+
+
+@blueprint.route('/verify_credentials/',
+                 methods=['POST'], endpoint='verify_credentials')
+@login_required
+def verify_credentials():
+    """Verify Credentials."""
+    data = json.loads(request.data, encoding='utf-8')
+    session_token = data['secret']['session_token'] if \
+        'session_token' in data['secret'] else None
+    tenant_id = data['secret']['azure_tenant_id'] if \
+        'azure_tenant_id' in data['secret'] else None
+    interactive_browser_credential = False if \
+        data['secret']['auth_type'] == 'azure_cli_credential' else True
+
+    if 'azure' not in session:
+        session['azure'] = {}
+
+    error = ''
+    status = True
+    if 'azure_obj' not in session['azure'] or \
+        session['azure']['auth_type'] != data['secret']['auth_type'] or \
+            session['azure']['azure_tenant_id'] != tenant_id:
+        azure = Azure(
+            interactive_browser_credential=interactive_browser_credential,
+            tenant_id=tenant_id,
+            session_token=session_token)
+        status, error = azure.validate_azure_credentials()
+        if status:
+            session['azure']['azure_obj'] = azure
+            session['azure']['auth_type'] = data['secret']['auth_type']
+            session['azure']['azure_tenant_id'] = tenant_id
+        if not status and 'double check your tenant name' in error:
+            error = 'Authentication failed.Please double check tenant id.'
+    return make_json_response(success=status, errormsg=error)
+
+
+@blueprint.route('/check_cluster_name_availability/',
+                 methods=['POST'], endpoint='check_cluster_name_availability')
+@login_required
+def check_cluster_name_availability():
+    """Check Server Name availability."""
+    data = json.loads(request.data, encoding='utf-8')
+    azure = session['azure']['azure_obj']
+    server_name_available, error = \
+        azure.check_cluster_name_availability(data['name'])
+    return make_json_response(success=server_name_available, errormsg=error)
+
+
+@blueprint.route('/subscriptions/',
+                 methods=['GET'], endpoint='subscriptions')
+@login_required
+def get_azure_subscriptions():
+    """
+    List subscriptions.
+    :return:
+    """
+    azure = session['azure']['azure_obj']
+    subscriptions_list = azure.list_subscriptions()
+    return make_json_response(data=subscriptions_list)
+
+
+@blueprint.route('/resource_groups/<subscription_id>',
+                 methods=['GET'], endpoint='resource_groups')
+@login_required
+def get_azure_resource_groups(subscription_id):
+    """
+    Fetch resource groups based on subscription.
+    """
+    if not subscription_id:
+        return make_json_response(data=[])
+    azure = session['azure']['azure_obj']
+    resource_groups_list = azure.list_resource_groups(subscription_id)
+    return make_json_response(data=resource_groups_list)
+
+
+@blueprint.route('/regions/<subscription_id>',
+                 methods=['GET'], endpoint='regions')
+@login_required
+def get_azure_regions(subscription_id):
+    """List Regions for Azure."""
+    if not subscription_id:
+        return make_json_response(data=[])
+    azure = session['azure']['azure_obj']
+    regions_list = azure.list_regions(subscription_id)
+    session['azure']['azure_obj'] = azure
+    return make_json_response(data=regions_list)
+
+
+@blueprint.route('/availability_zones/<region_name>',
+                 methods=['GET'], endpoint='availability_zones')
+@login_required
+def get_azure_availability_zones(region_name):
+    """List availability zones in given region."""
+    if not region_name:
+        return make_json_response(data=[])
+    azure = session['azure']['azure_obj']
+    availability_zones = azure.list_azure_availability_zones(region_name)
+    session['azure']['azure_obj'] = azure
+    return make_json_response(data=availability_zones)
+
+
+@blueprint.route('/db_versions/<availability_zone>',
+                 methods=['GET'], endpoint='db_versions')
+@login_required
+def get_azure_postgresql_server_versions(availability_zone):
+    """Get azure postgres database versions."""
+    if not availability_zone:
+        return make_json_response(data=[])
+    azure = session['azure']['azure_obj']
+    azure_postgresql_server_versions = \
+        azure.list_azure_postgresql_server_versions(availability_zone)
+    session['azure']['azure_obj'] = azure
+    return make_json_response(data=azure_postgresql_server_versions)
+
+
+@blueprint.route('/instance_types/<availability_zone>/<db_version>',
+                 methods=['GET'], endpoint='instance_types')
+@login_required
+def get_azure_instance_types(availability_zone, db_version):
+    """Get instance types for Azure."""
+    if not db_version:
+        return make_json_response(data=[])
+    azure = session['azure']['azure_obj']
+    instance_types = azure.list_compute_types(availability_zone, db_version)
+    return make_json_response(data=instance_types)
+
+
+@blueprint.route('/storage_types/<availability_zone>/<db_version>',
+                 methods=['GET'], endpoint='storage_types')
+@login_required
+def list_azure_storage_types(availability_zone, db_version):
+    """Get the storage types supported."""
+    if not db_version:
+        return make_json_response(data=[])
+    azure = session['azure']['azure_obj']
+    storage_types = azure.list_storage_types(availability_zone, db_version)
+    return make_json_response(data=storage_types)
+
+
+@blueprint.route('/clear_session',
+                 methods=['GET'], endpoint='clear_session')
+@login_required
+def clear_session():
+    clear_azure_session()
+    return make_json_response(success=1)
+
+
+class Azure:
+    def __init__(self, interactive_browser_credential, tenant_id=None,
+                 session_token=None, region='eastus'):
+        self._clients = {}
+        self._tenant_id = tenant_id
+        self._session_token = session_token
+        self._use_interactive_browser_credential = \
+            interactive_browser_credential
+        self.authentication_record_json = None
+        self._cli_credentials = None
+        self._credentials = None
+        self._region = region
+        self.subscription_id = None
+        self._availability_zone = None
+        self._available_capabilities_list = []
+
+    ##########################################################################
+    # Azure Helper functions
+    ##########################################################################
+
+    def validate_azure_credentials(self):
+        """
+        Validates azure credentials
+        :return: True if valid credentials else false
+        """
+        status, identity = self._get_azure_credentials()
+        error = ''
+        if not status:
+            error = identity
+        return status, error
+
+    def _get_azure_credentials(self):
+        """
+        Gets azure credentials depending on
+        self._use_interactive_browser_credential
+        :return:
+        """
+        try:
+            if self._use_interactive_browser_credential:
+                if self.authentication_record_json is None:
+                    _credentials = self._azure_interactive_browser_credential()
+                    _auth_record_ = _credentials.authenticate()
+                    self.authentication_record_json = _auth_record_.serialize()
+                else:
+                    deserialized_auth_record = AuthenticationRecord. \
+                        deserialize(self.authentication_record_json)
+                    _credentials = \
+                        self._azure_interactive_browser_credential(
+                            deserialized_auth_record)
+            else:
+                if self._cli_credentials is None:
+                    self._cli_credentials = AzureCliCredential()
+                    self.list_subscriptions()
+                _credentials = self._cli_credentials
+        except Exception as e:
+            return False, str(e)
+        return True, _credentials
+
+    def _azure_interactive_browser_credential(
+            self, deserialized_auth_record=None):
+        if deserialized_auth_record:
+            _credential = InteractiveBrowserCredential(
+                tenant_id=self._tenant_id,
+                timeout=180,
+                cache_persistence_options=TokenCachePersistenceOptions(),
+                authentication_record=deserialized_auth_record)
+        else:
+            _credential = InteractiveBrowserCredential(
+                tenant_id=self._tenant_id,
+                timeout=180,
+                cache_persistence_options=TokenCachePersistenceOptions())
+        return _credential
+
+    def _get_azure_client(self, type):
+        """ Create/cache/return an Azure client object """
+        if type in self._clients:
+            return self._clients[type]
+
+        status, _credentials = self._get_azure_credentials()
+
+        if type == 'postgresql':
+            client = PostgreSQLManagementClient(_credentials,
+                                                self.subscription_id)
+        elif type == 'resource':
+            client = ResourceManagementClient(_credentials,
+                                              self.subscription_id)
+        elif type == 'subscription':
+            client = SubscriptionClient(_credentials)
+
+        self._clients[type] = client
+        return self._clients[type]
+
+    def check_cluster_name_availability(self, cluster_name):
+        """
+        Checks whether given server name is available or not
+        :param cluster_name
+        """
+        postgresql_client = self._get_azure_client('postgresql')
+        res = postgresql_client.check_name_availability.execute(
+            NameAvailabilityRequest(
+                name=cluster_name,
+                type='Microsoft.DBforPostgreSQL/flexibleServers'))
+        res = res.__dict__
+        return res['name_available'], res['message']
+
+    def list_subscriptions(self):
+        """
+        List subscriptions
+        :return:
+        """
+        subscription_client = self._get_azure_client('subscription')
+        sub_list = subscription_client.subscriptions.list()
+        subscriptions_list = []
+        for group in list(sub_list):
+            subscriptions_list.append(
+                {'subscription_id': group.subscription_id,
+                 'subscription_name': group.display_name})
+        return subscriptions_list
+
+    def list_resource_groups(self, subscription_id):
+        """
+        List the resource groups
+        :param subscription_id:
+        :return:
+        """
+        self.subscription_id = subscription_id
+        resource_client = self._get_azure_client('resource')
+        group_list = resource_client.resource_groups.list()
+        resource_groups_list = []
+        for group in list(group_list):
+            resource_groups_list.append(
+                {'label': group.name,
+                 'value': group.name,
+                 'region': group.location})
+        return resource_groups_list
+
+    def list_regions(self, subscription_id):
+        """
+        List regions depending on subscription id
+        :param subscription_id:
+        :return:
+        """
+        self.subscription_id = subscription_id
+        subscription_client = self._get_azure_client('subscription')
+        locations = subscription_client.subscriptions.list_locations(
+            subscription_id=self.subscription_id)
+        locations_list = []
+        for location in locations:
+            locations_list.append(
+                {'label': location.display_name, 'value': location.name})
+        return locations_list
+
+    def list_azure_availability_zones(self, region):
+        """
+        List availability zones in the region
+        :param region:
+        :return:
+        """
+        self._region = region
+        self._available_capabilities_list = \
+            self._get_available_capabilities_list(region)
+        availability_zones_list = []
+        for capability in self._available_capabilities_list:
+            zone = str(capability['zone'])
+            if capability['zone'] == 'none':
+                availability_zones_list.append({'label': 'No Preference',
+                                                'value': zone})
+            else:
+                availability_zones_list.append({'label': zone,
+                                                'value': zone})
+        return availability_zones_list
+
+    def list_azure_postgresql_server_versions(self, availability_zone):
+        """
+        :param availability_zone:
+        :return: List of postgresql version available in specified availability
+        zone.
+        """
+        self._availability_zone = availability_zone
+        server_versions_list = []
+        for capability in self._available_capabilities_list:
+            if str(capability['zone']) == availability_zone:
+                for supported_server_version in \
+                        capability['supported_server_versions']:
+                    server_version = supported_server_version['server_version']
+                    server_versions_list.append({'label': str(server_version),
+                                                 'value': server_version})
+        return server_versions_list
+
+    def list_compute_types(self, availability_zone, server_version):
+        """
+        :param availability_zone:
+        :param server_version:
+        :return: list of compute classes based on specified availability
+        zone & server version.
+        """
+        compute_types_list = []
+        for capability in self._available_capabilities_list:
+            if str(capability['zone']) == availability_zone:
+                for supported_server_version in \
+                        capability['supported_server_versions']:
+                    if supported_server_version['server_version'] == \
+                            server_version:
+                        compute_types = \
+                            supported_server_version['compute_types']
+                        for value in compute_types:
+                            compute_types_list.append(
+                                {'label': value['display_name'],
+                                 'value': value['name'],
+                                 'type': value['type']})
+        return compute_types_list
+
+    def list_storage_types(self, availability_zone, server_version):
+        """
+
+        :param availability_zone:
+        :param server_version:
+        :return:  list of storages classes based on specified availability
+        """
+        storage_types_list = []
+
+        for capability in self._available_capabilities_list:
+            if str(capability['zone']) == availability_zone:
+                for supported_server_version in \
+                        capability['supported_server_versions']:
+                    if supported_server_version['server_version'] == \
+                            server_version:
+                        storage_types = \
+                            supported_server_version['storage_types']
+                        for value in storage_types:
+                            storage_types_list.append(
+                                {'label': str(value['storage_size_gb']),
+                                 'value': value['storage_size_gb'],
+                                 'type': value['type']})
+        return storage_types_list
+
+    def _get_available_capabilities_list(self, region):
+        """
+        list capabilities & serialize them to normal list-dict format
+        :param region:
+        :return:
+        """
+        available_capabilities = \
+            self._get_available_capabilities_object(region)
+        return self.\
+            _serialize_available_capabilities_list(available_capabilities)
+
+    def _get_available_capabilities_object(self, region):
+        """
+        :param region:
+        :return: azure capabilities object
+        """
+        postgresql_client = self._get_azure_client('postgresql')
+        return postgresql_client.location_based_capabilities.execute(
+            location_name=region)
+
+    @staticmethod
+    def _serialize_available_capabilities_list(available_capabilities):
+        """
+        :param available_capabilities:
+        :return: serialized available capabilities list
+        """
+        available_capabilities_list = []
+        for capability in available_capabilities:
+            supported_server_version_dict = {}
+            storage_types = []
+            for supported_flexible_server_edition in \
+                    capability.supported_flexible_server_editions:
+                compute_type = supported_flexible_server_edition.name
+
+                storage_types = Azure. \
+                    _get_storage_types(compute_type,
+                                       supported_flexible_server_edition,
+                                       storage_types)
+
+                supported_server_version_dict = Azure. \
+                    _get_compute_types(compute_type,
+                                       supported_flexible_server_edition,
+                                       supported_server_version_dict,
+                                       storage_types)
+
+            supported_server_version_list = []
+            for key, value in supported_server_version_dict.items():
+                supported_server_version_list.append(
+                    {'server_version': key,
+                     'compute_types': value['compute_types'],
+                     'storage_types': value['storage_types']})
+
+            available_capabilities_list.append(
+                {'zone': capability.zone,
+                 'supported_server_versions': supported_server_version_list})
+
+        return available_capabilities_list
+
+    @staticmethod
+    def _get_storage_types(compute_type, supported_flexible_server_edition,
+                           storage_types):
+        for supported_storage_edition in \
+                supported_flexible_server_edition.supported_storage_editions:
+            for supported_storage_mb in \
+                    supported_storage_edition.supported_storage_mb:
+                supported_storage_mb_dict = supported_storage_mb.__dict__
+                storage_types.append({'type': compute_type,
+                                      'storage_size_gb':
+                                          int(supported_storage_mb_dict[
+                                              'storage_size_mb'] / 1024)})
+        return storage_types
+
+    @staticmethod
+    def _get_compute_types(compute_type, supported_flexible_server_edition,
+                           supported_server_version_dict, storage_types):
+        for supported_server_version in \
+                supported_flexible_server_edition.supported_server_versions:
+            if not supported_server_version.name.isnumeric():
+                continue
+
+            if supported_server_version.name not in \
+                    supported_server_version_dict:
+                supported_server_version_dict[
+                    supported_server_version.name] = {}
+
+            compute_types_list = []
+            for supported_vcore in supported_server_version.supported_vcores:
+                vcore_dict = supported_vcore.__dict__
+                compute_types_list.append(
+                    {'type': compute_type,
+                     'name': vcore_dict['name'],
+                     'supportedIOPS': vcore_dict['additional_properties'][
+                         'supportedIOPS'],
+                     'display_name': vcore_dict['name'] + ' (' +
+                        str(vcore_dict['v_cores']) + ' vCores, ' +
+                        str(int(vcore_dict['supported_memory_per_vcore_mb'] /
+                            1024 * vcore_dict['v_cores'])) + 'GiB memory, ' +
+                        str(vcore_dict['additional_properties']
+                            ['supportedIOPS']) +
+                        ' max iops)'
+                     })
+
+            if 'compute_types' not in supported_server_version_dict[
+                    supported_server_version.name]:
+                supported_server_version_dict[supported_server_version.name][
+                    'compute_types'] = compute_types_list
+            else:
+                supported_server_version_dict[supported_server_version.name][
+                    'compute_types'] = \
+                    supported_server_version_dict[
+                        supported_server_version.name]['compute_types'] + (
+                        compute_types_list)
+
+            supported_server_version_dict[supported_server_version.name][
+                'storage_types'] = storage_types
+
+        return supported_server_version_dict
+
+
+def deploy_on_azure(data):
+    """Deploy the Postgres instance on Azure."""
+    _cmd = 'python'
+    _cmd_script = '{0}/pgacloud/pgacloud.py'.format(root)
+    _label = data['instance_details']['name']
+
+    args = [_cmd_script,
+
+            'azure',
+
+            '--region',
+            str(data['instance_details']['region']),
+
+            '--resource-group',
+            data['instance_details']['resource_group'],
+
+            'create-instance',
+            '--name',
+            data['instance_details']['name'],
+
+            '--db-username',
+            data['db_details']['db_username'],
+
+            '--db-password',
+            data['db_details']['db_password'],
+
+            '--db-major-version',
+            str(data['instance_details']['db_version']),
+
+            '--instance_tier_type',
+            data['instance_details']['db_instance_class'],
+
+            '--instance-type',
+            data['instance_details']['instance_type'],
+
+            '--storage-size',
+            str(data['instance_details']['storage_size']),
+
+            '--public-ips',
+            str(data['instance_details']['public_ips']),
+
+            '--availability-zone',
+            str(data['instance_details']['availability_zone'])]
+
+    _cmd_msg = '{0} {1} {2}'.format(_cmd, _cmd_script, ' '.join(args))
+    try:
+        sid = _create_server({
+            'gid': data['db_details']['gid'],
+            'name': data['instance_details']['name'],
+            'db': 'postgres',
+            'username': data['db_details']['db_username'],
+            'port': 5432,
+            'cloud_status': -1
+        })
+
+        p = BatchProcess(
+            desc=CloudProcessDesc(sid, _cmd_msg, data['cloud'],
+                                  data['instance_details']['name']),
+            cmd=_cmd,
+            args=args
+        )
+
+        env = dict()
+
+        azure = session['azure']['azure_obj']
+        env['AZURE_SUBSCRIPTION_ID'] = azure.subscription_id
+        env['AUTH_TYPE'] = data['secret']['auth_type']
+        if azure.authentication_record_json is not None:
+            env['AUTHENTICATION_RECORD_JSON'] = \
+                azure.authentication_record_json
+            env['AZURE_TENANT_ID'] = data['secret']['azure_tenant_id']
+
+        p.set_env_variables(None, env=env)
+        p.update_server_id(p.id, sid)
+        p.start()
+        del session['azure']['azure_obj']
+        return True, {'label': _label, 'sid': sid}
+    except Exception as e:
+        current_app.logger.exception(e)
+        return False, str(e)
+
+
+def clear_azure_session():
+    """Clear session data."""
+    if 'azure' in session:
+        session.pop('azure')
diff --git a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
index 7c191b95d..da5391810 100644
--- a/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
+++ b/web/pgadmin/misc/cloud/static/js/CloudWizard.jsx
@@ -21,12 +21,12 @@ import PropTypes from 'prop-types';
 import pgAdmin from 'sources/pgadmin';
 import {ToggleButtons, FinalSummary} from './cloud_components';
 import { PrimaryButton } from '../../../../static/js/components/Buttons';
-import {AwsCredentials, AwsInstanceDetails, AwsDatabaseDetails, validateCloudStep1,
-  validateCloudStep2, validateCloudStep3} from './aws';
-import {BigAnimalInstance, BigAnimalDatabase, validateBigAnimal,
-  validateBigAnimalStep2, validateBigAnimalStep3} from './biganimal';
+import {AwsCredentials, AwsInstanceDetails, AwsDatabaseDetails, validateCloudStep1, validateCloudStep2, validateCloudStep3} from './aws';
+import {BigAnimalInstance, BigAnimalDatabase, validateBigAnimal,validateBigAnimalStep2, validateBigAnimalStep3} from './biganimal';
 import { isEmptyString } from 'sources/validators';
-import { AWSIcon, BigAnimalIcon } from '../../../../static/js/components/ExternalIcon';
+import { AWSIcon, BigAnimalIcon, AzureIcon } from '../../../../static/js/components/ExternalIcon';
+import {AzureCredentials, AzureInstanceDetails, AzureDatabaseDetails, validateAzureStep2, validateAzureStep3} from './azure';
+import EventBus from '../../../../static/js/helpers/EventBus';
 
 const useStyles = makeStyles(() =>
   ({
@@ -53,12 +53,20 @@ const useStyles = makeStyles(() =>
     boxText: {
       paddingBottom: '5px'
     },
+    authButton: {
+      marginLeft: '12em'
+    }
   }),
 );
 
+export const CloudWizardEventsContext = React.createContext();
+
+
 export default function CloudWizard({ nodeInfo, nodeData }) {
   const classes = useStyles();
 
+  const eventBus = React.useRef(new EventBus());
+
   var steps = [gettext('Cloud Provider'), gettext('Credentials'),
     gettext('Instance Specification'), gettext('Database Details'), gettext('Review')];
   const [currentStep, setCurrentStep] = React.useState('');
@@ -74,13 +82,27 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
   const [bigAnimalInstanceData, setBigAnimalInstanceData] = React.useState({});
   const [bigAnimalDatabaseData, setBigAnimalDatabaseData] = React.useState({});
 
-
+  const [azureCredData, setAzureCredData] = React.useState({});
+  const [azureInstanceData, setAzureInstanceData] = React.useState({});
+  const [azureDatabaseData, setAzureDatabaseData] = React.useState({});
 
   const axiosApi = getApiInstance();
 
   const [verificationURI, setVerificationURI] = React.useState('');
   const [verificationCode, setVerificationCode] = React.useState('');
 
+  React.useEffect(()=>{
+    eventBus.current.registerListener('SET_ERROR_MESSAGE_FOR_CLOUD_WIZARD', (msg) => {
+      setErrMsg(msg);
+    });
+  }, []);
+
+  React.useEffect(()=>{
+    eventBus.current.registerListener('SET_CRED_VERIFICATION_INITIATED', (initiated) => {
+      setVerificationIntiated(initiated);
+    });
+  }, []);
+
   React.useEffect(() => {
     let _url = url_for('cloud.get_host_ip') ;
     axiosApi.get(_url)
@@ -110,7 +132,16 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
         instance_details:cloudInstanceDetails,
         db_details: cloudDBDetails
       };
-    } else {
+    } else if(cloudProvider == 'azure'){
+      post_data = {
+        gid: nodeInfo.server_group._id,
+        secret: azureCredData,
+        cloud: cloudProvider,
+        instance_details:azureInstanceData,
+        db_details: azureDatabaseData
+      };
+
+    }else {
       post_data = {
         gid: nodeInfo.server_group._id,
         cloud: cloudProvider,
@@ -170,6 +201,24 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
         break;
       }
       break;
+    case 'azure':
+      switch (currentStep) {
+      case 0:
+        setCloudSelection('azure');
+        break;
+      case 1:
+        isError = !verificationIntiated;
+        break;
+      case 2:
+        isError = validateAzureStep2(azureInstanceData);
+        break;
+      case 3:
+        isError = validateAzureStep3(azureDatabaseData, nodeInfo);
+        break;
+      default:
+        break;
+      }
+      break;
     }
     return isError;
   };
@@ -213,6 +262,7 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
           });
       }
       else {
+        setErrMsg(['', '']);
         resolve();
       }
     });
@@ -262,96 +312,122 @@ export default function CloudWizard({ nodeInfo, nodeData }) {
   });
 
   return (
-    <>
-      <Wizard
-        title={gettext('Deploy Cloud Instance')}
-        stepList={steps}
-        disableNextStep={disableNextCheck}
-        onStepChange={wizardStepChange}
-        onSave={onSave}
-        onHelp={onDialogHelp}
-        beforeNext={onBeforeNext}>
-        <WizardStep stepId={0}>
-          <Box className={classes.messageBox}>
-            <Box className={classes.messagePadding}>{gettext('Select any option to deploy on cloud.')}</Box>
-          </Box>
-          <Box className={classes.messageBox}>
-            <ToggleButtons cloudProvider={cloudProvider} setCloudProvider={setCloudProvider}
-              options={[{label: 'Amazon RDS', value: 'rds', icon: <AWSIcon className={classes.icon} />}, {label: 'EDB BigAnimal', value: 'biganimal', icon: <BigAnimalIcon className={classes.icon} />}]}
-            ></ToggleButtons>
-          </Box>
-          <Box className={classes.messageBox}>
-            <Box className={classes.messagePadding}>{gettext('More cloud providers are coming soon...')}</Box>
-          </Box>
-          <FormFooterMessage type={errMsg[0]} message={errMsg[1]} onClose={onErrClose} />
-        </WizardStep>
-        <WizardStep stepId={1} >
-          <Box className={classes.buttonMarginEDB}>
-            {cloudProvider == 'biganimal' && <Box className={classes.messageBox}>
-              <Box>{gettext('The verification code to authenticate the pgAdmin to EDB BigAnimal is: ')} <strong>{verificationCode}</strong>
-                <br/>{gettext('By clicking the below button, you will be redirected to the EDB BigAnimal authentication page in a new tab.')}
-              </Box>
-            </Box>}
-            {cloudProvider == 'biganimal' && <PrimaryButton onClick={authenticateBigAnimal} disabled={verificationIntiated ? true: false}>
-              {gettext('Click here to authenticate yourself to EDB BigAnimal')}
-            </PrimaryButton>}
-            {cloudProvider == 'biganimal' && <Box className={classes.messageBox}>
-              <Box ></Box>
-            </Box>}
-          </Box>
-          {cloudProvider == 'rds' && <AwsCredentials cloudProvider={cloudProvider} nodeInfo={nodeInfo} nodeData={nodeData} setCloudDBCred={setCloudDBCred}/>}
-          <FormFooterMessage type={errMsg[0]} message={errMsg[1]} onClose={onErrClose} />
-        </WizardStep>
-        <WizardStep stepId={2} >
-          {cloudProvider == 'rds' && callRDSAPI == 2 && <AwsInstanceDetails
-            cloudProvider={cloudProvider}
-            nodeInfo={nodeInfo}
-            nodeData={nodeData}
-            setCloudInstanceDetails={setCloudInstanceDetails}
-            hostIP={hostIP} /> }
-          {cloudProvider == 'biganimal' && callRDSAPI == 2 && <BigAnimalInstance
-            cloudProvider={cloudProvider}
-            nodeInfo={nodeInfo}
-            nodeData={nodeData}
-            setBigAnimalInstanceData={setBigAnimalInstanceData}
-            hostIP={hostIP}
-          /> }
-        </WizardStep>
-        <WizardStep stepId={3} >
-          {cloudProvider == 'rds' && <AwsDatabaseDetails
-            cloudProvider={cloudProvider}
-            nodeInfo={nodeInfo}
-            nodeData={nodeData}
-            setCloudDBDetails={setCloudDBDetails}
-          />
-          }
-          {cloudProvider == 'biganimal' && callRDSAPI == 3 && <BigAnimalDatabase
-            cloudProvider={cloudProvider}
-            nodeInfo={nodeInfo}
-            nodeData={nodeData}
-            setBigAnimalDatabaseData={setBigAnimalDatabaseData}
-          />
-          }
-        </WizardStep>
-        <WizardStep stepId={4} >
-          <Box className={classes.boxText}>{gettext('Please review the details before creating the cloud instance.')}</Box>
-          <Paper variant="outlined" elevation={0} className={classes.summaryContainer}>
-            {cloudProvider == 'rds' && callRDSAPI == 4 && <FinalSummary
+    <CloudWizardEventsContext.Provider value={eventBus.current}>
+      <>
+        <Wizard
+          title={gettext('Deploy Cloud Instance')}
+          stepList={steps}
+          disableNextStep={disableNextCheck}
+          onStepChange={wizardStepChange}
+          onSave={onSave}
+          onHelp={onDialogHelp}
+          beforeNext={onBeforeNext}>
+          <WizardStep stepId={0}>
+            <Box className={classes.messageBox}>
+              <Box className={classes.messagePadding}>{gettext('Select any option to deploy on cloud.')}</Box>
+            </Box>
+            <Box className={classes.messageBox}>
+              <ToggleButtons cloudProvider={cloudProvider} setCloudProvider={setCloudProvider}
+                options={[{label: 'Amazon RDS', value: 'rds', icon: <AWSIcon className={classes.icon} />}, {label: 'EDB BigAnimal', value: 'biganimal', icon: <BigAnimalIcon className={classes.icon} />}, {'label': 'Azure Postgresql', value: 'azure', icon: <AzureIcon className={classes.icon} /> }]}
+              ></ToggleButtons>
+            </Box>
+            <Box className={classes.messageBox}>
+              <Box className={classes.messagePadding}>{gettext('More cloud providers are coming soon...')}</Box>
+            </Box>
+            <FormFooterMessage type={errMsg[0]} message={errMsg[1]} onClose={onErrClose} />
+          </WizardStep>
+          <WizardStep stepId={1} >
+            <Box className={classes.buttonMarginEDB}>
+              {cloudProvider == 'biganimal' && <Box className={classes.messageBox}>
+                <Box>{gettext('The verification code to authenticate the pgAdmin to EDB BigAnimal is: ')} <strong>{verificationCode}</strong>
+                  <br/>{gettext('By clicking the below button, you will be redirected to the EDB BigAnimal authentication page in a new tab.')}
+                </Box>
+              </Box>}
+              {cloudProvider == 'biganimal' && <PrimaryButton onClick={authenticateBigAnimal} disabled={verificationIntiated ? true: false}>
+                {gettext('Click here to authenticate yourself to EDB BigAnimal')}
+              </PrimaryButton>}
+              {cloudProvider == 'biganimal' && <Box className={classes.messageBox}>
+                <Box ></Box>
+              </Box>}
+            </Box>
+            {cloudProvider == 'rds' && <AwsCredentials cloudProvider={cloudProvider} nodeInfo={nodeInfo} nodeData={nodeData} setCloudDBCred={setCloudDBCred}/>}
+            <Box>
+              {cloudProvider == 'azure' && <AzureCredentials cloudProvider={cloudProvider} nodeInfo={nodeInfo} nodeData={nodeData} setAzureCredData={setAzureCredData}/>}
+            </Box>
+            <FormFooterMessage type={errMsg[0]} message={errMsg[1]} onClose={onErrClose} />
+          </WizardStep>
+          <WizardStep stepId={2} >
+            {cloudProvider == 'rds' && callRDSAPI == 2 && <AwsInstanceDetails
+              cloudProvider={cloudProvider}
+              nodeInfo={nodeInfo}
+              nodeData={nodeData}
+              setCloudInstanceDetails={setCloudInstanceDetails}
+              hostIP={hostIP} /> }
+            {cloudProvider == 'biganimal' && callRDSAPI == 2 && <BigAnimalInstance
+              cloudProvider={cloudProvider}
+              nodeInfo={nodeInfo}
+              nodeData={nodeData}
+              setBigAnimalInstanceData={setBigAnimalInstanceData}
+              hostIP={hostIP}
+            /> }
+            {cloudProvider == 'azure' && callRDSAPI == 2 && <AzureInstanceDetails
               cloudProvider={cloudProvider}
-              instanceData={cloudInstanceDetails}
-              databaseData={cloudDBDetails}
+              nodeInfo={nodeInfo}
+              nodeData={nodeData}
+              setAzureInstanceData={setAzureInstanceData}
+              hostIP={hostIP}
+              azureInstanceData = {azureInstanceData}
+            /> }
+          </WizardStep>
+          <WizardStep stepId={3} >
+            {cloudProvider == 'rds' && <AwsDatabaseDetails
+              cloudProvider={cloudProvider}
+              nodeInfo={nodeInfo}
+              nodeData={nodeData}
+              setCloudDBDetails={setCloudDBDetails}
             />
             }
-            {cloudProvider == 'biganimal' && callRDSAPI == 4 && <FinalSummary
+            {cloudProvider == 'biganimal' && callRDSAPI == 3 && <BigAnimalDatabase
               cloudProvider={cloudProvider}
-              instanceData={bigAnimalInstanceData}
-              databaseData={bigAnimalDatabaseData}
+              nodeInfo={nodeInfo}
+              nodeData={nodeData}
+              setBigAnimalDatabaseData={setBigAnimalDatabaseData}
             />
             }
-          </Paper>
-        </WizardStep>
-      </Wizard>
-    </>
+            {cloudProvider == 'azure' && <AzureDatabaseDetails
+              cloudProvider={cloudProvider}
+              nodeInfo={nodeInfo}
+              nodeData={nodeData}
+              setAzureDatabaseData={setAzureDatabaseData}
+            />
+            }
+          </WizardStep>
+          <WizardStep stepId={4} >
+            <Box className={classes.boxText}>{gettext('Please review the details before creating the cloud instance.')}</Box>
+            <Paper variant="outlined" elevation={0} className={classes.summaryContainer}>
+              {cloudProvider == 'rds' && callRDSAPI == 4 && <FinalSummary
+                cloudProvider={cloudProvider}
+                instanceData={cloudInstanceDetails}
+                databaseData={cloudDBDetails}
+              />
+              }
+              {cloudProvider == 'biganimal' && callRDSAPI == 4 && <FinalSummary
+                cloudProvider={cloudProvider}
+                instanceData={bigAnimalInstanceData}
+                databaseData={bigAnimalDatabaseData}
+              />
+              }
+              {cloudProvider == 'azure' && callRDSAPI == 4 && <FinalSummary
+                cloudProvider={cloudProvider}
+                instanceData={azureInstanceData}
+                databaseData={azureDatabaseData}
+              />
+              }
+            </Paper>
+          </WizardStep>
+        </Wizard>
+      </>
+    </CloudWizardEventsContext.Provider>
   );
 }
 
@@ -359,5 +435,3 @@ CloudWizard.propTypes = {
   nodeInfo: PropTypes.object,
   nodeData: PropTypes.object,
 };
-
-
diff --git a/web/pgadmin/misc/cloud/static/js/azure.js b/web/pgadmin/misc/cloud/static/js/azure.js
new file mode 100644
index 000000000..559caa347
--- /dev/null
+++ b/web/pgadmin/misc/cloud/static/js/azure.js
@@ -0,0 +1,221 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+import React from 'react';
+import {AzureCredSchema, AzureClusterSchema, AzureDatabaseSchema} from './azure_schema.ui';
+import pgAdmin from 'sources/pgadmin';
+import { getNodeAjaxOptions, getNodeListById } from 'pgbrowser/node_ajax';
+import SchemaView from '../../../../static/js/SchemaView';
+import url_for from 'sources/url_for';
+import { isEmptyString } from 'sources/validators';
+import PropTypes from 'prop-types';
+
+// Azure credentials
+export function AzureCredentials(props) {
+  const [cloudDBCredInstance, setCloudDBCredInstance] = React.useState();
+
+  React.useMemo(() => {
+    const azureCloudDBCredSchema = new AzureCredSchema({});
+    setCloudDBCredInstance(azureCloudDBCredSchema);
+  }, [props.cloudProvider]);
+
+  return  <SchemaView
+    formType={'dialog'}
+    getInitData={() => { /*This is intentional (SonarQube)*/ }}
+    viewHelperProps={{ mode: 'create' }}
+    schema={cloudDBCredInstance}
+    showFooter={false}
+    isTabView={false}
+    onDataChange={(isChanged, changedData) => {
+      props.setAzureCredData(changedData);
+    }}
+  />;
+}
+AzureCredentials.propTypes = {
+  nodeInfo: PropTypes.object,
+  nodeData: PropTypes.object,
+  cloudProvider: PropTypes.string,
+  setAzureCredData: PropTypes.func
+};
+
+
+// Azure Instance
+export function AzureInstanceDetails(props) {
+  const [azureInstanceSchema, setAzureInstanceSchema] = React.useState();
+
+  React.useMemo(() => {
+    const AzureSchema = new AzureClusterSchema({
+      subscriptions: () => getNodeAjaxOptions('get_subscriptions', {}, {}, {},{
+        useCache:false,
+        cacheNode: 'server',
+        customGenerateUrl: ()=>{
+          return url_for('azure.subscriptions');
+        }
+      }),
+      resourceGroups: (subscription)=>getNodeAjaxOptions('ge_resource_groups', pgAdmin.Browser.Nodes['server'], props.nodeInfo, props.nodeData, {
+        useCache:false,
+        cacheNode: 'server',
+        customGenerateUrl: ()=>{
+          return url_for('azure.resource_groups', {'subscription_id': subscription});
+        }
+      }),
+      regions: (subscription)=>getNodeAjaxOptions('get_regions', pgAdmin.Browser.Nodes['server'], props.nodeInfo, props.nodeData, {
+        useCache:false,
+        cacheNode: 'server',
+        customGenerateUrl: ()=>{
+          return url_for('azure.regions', {'subscription_id': subscription});
+        }
+      }),
+      availabilityZones:(region)=>getNodeAjaxOptions('get_availability_zones', pgAdmin.Browser.Nodes['server'], props.nodeInfo, props.nodeData, {
+        useCache:false,
+        cacheNode: 'server',
+        customGenerateUrl: ()=>{
+          return url_for('azure.availability_zones', {'region_name': region});
+        }
+      }),
+      versionOptions:(availabilityZone)=>getNodeAjaxOptions('get_db_versions', pgAdmin.Browser.Nodes['server'], props.nodeInfo, props.nodeData, {
+        useCache:false,
+        cacheNode: 'server',
+        customGenerateUrl: ()=>{
+          return url_for('azure.db_versions', {'availability_zone': availabilityZone});
+        }
+      }),
+      instanceOptions:(dbVersion, availabilityZone)=>getNodeAjaxOptions('get_instance_types', pgAdmin.Browser.Nodes['server'], props.nodeInfo, props.nodeData, {
+        useCache:false,
+        cacheNode: 'server',
+        customGenerateUrl: ()=>{
+          return url_for('azure.instance_types', {'availability_zone':availabilityZone, 'db_version': dbVersion});
+        }
+      }),
+      storageOptions:(dbVersion, availabilityZone)=>getNodeAjaxOptions('get_instance_types', pgAdmin.Browser.Nodes['server'], props.nodeInfo, props.nodeData, {
+        useCache:false,
+        cacheNode: 'server',
+        customGenerateUrl: ()=>{
+          return url_for('azure.storage_types', {'availability_zone':availabilityZone, 'db_version': dbVersion});
+        }
+      })
+    }, {
+      nodeInfo: props.nodeInfo,
+      nodeData: props.nodeData,
+      hostIP: props.hostIP,
+      ...props.azureInstanceData
+    });
+    setAzureInstanceSchema(AzureSchema);
+  }, [props.cloudProvider]);
+
+  return  <SchemaView
+    formType={'dialog'}
+    getInitData={() => { /*This is intentional (SonarQube)*/ }}
+    viewHelperProps={{ mode: 'create' }}
+    schema={azureInstanceSchema}
+    showFooter={false}
+    isTabView={false}
+    onDataChange={(isChanged, changedData) => {
+      props.setAzureInstanceData(changedData);
+    }}
+  />;
+}
+AzureInstanceDetails.propTypes = {
+  nodeInfo: PropTypes.object,
+  nodeData: PropTypes.object,
+  cloudProvider: PropTypes.string,
+  setAzureInstanceData: PropTypes.func,
+  hostIP: PropTypes.string,
+  subscriptions: PropTypes.array,
+  azureInstanceData: PropTypes.object
+};
+
+
+// Azure Database Details
+export function AzureDatabaseDetails(props) {
+  const [azureDBInstance, setAzureDBInstance] = React.useState();
+
+  React.useMemo(() => {
+    const azureDBSchema = new AzureDatabaseSchema({
+      server_groups: ()=>getNodeListById(pgAdmin.Browser.Nodes['server_group'], props.nodeInfo, props.nodeData),
+    },
+    {
+      gid: props.nodeInfo['server_group']._id,
+    }
+    );
+    setAzureDBInstance(azureDBSchema);
+
+  }, [props.cloudProvider]);
+
+  return <SchemaView
+    formType={'dialog'}
+    getInitData={() => { /*This is intentional (SonarQube)*/ }}
+    viewHelperProps={{ mode: 'create' }}
+    schema={azureDBInstance}
+    showFooter={false}
+    isTabView={false}
+    onDataChange={(isChanged, changedData) => {
+      props.setAzureDatabaseData(changedData);
+    }}
+  />;
+}
+AzureDatabaseDetails.propTypes = {
+  nodeInfo: PropTypes.object,
+  nodeData: PropTypes.object,
+  cloudProvider: PropTypes.string,
+  setAzureDatabaseData: PropTypes.func,
+};
+
+
+// Validation functions
+export function validateAzureStep2(cloudInstanceDetails) {
+  let isError = false;
+  if (isEmptyString(cloudInstanceDetails.name) ||
+  isEmptyString(cloudInstanceDetails.db_version) || isEmptyString(cloudInstanceDetails.instance_type) ||
+  isEmptyString(cloudInstanceDetails.region)|| isEmptyString(cloudInstanceDetails.storage_size || isEmptyString(cloudInstanceDetails.public_ips))) {
+    isError = true;
+  }
+  return isError;
+}
+
+export function validateAzureStep3(cloudDBDetails, nodeInfo) {
+  let isError = false;
+  if (isEmptyString(cloudDBDetails.db_username) || isEmptyString(cloudDBDetails.db_password)) {
+    isError = true;
+  }
+  if (isEmptyString(cloudDBDetails.gid)) cloudDBDetails.gid = nodeInfo['server_group']._id;
+  return isError;
+}
+
+// Summary creation
+function createData(name, value) {
+  return { name, value };
+}
+
+// Summary section
+export function getAzureSummary(cloud, cloudInstanceDetails, cloudDBDetails) {
+  const rows1 = [
+    createData('Cloud', cloud),
+    createData('Subscription', cloudInstanceDetails.subscription),
+    createData('Resource Group', cloudInstanceDetails.resource_group),
+    createData('Region', cloudInstanceDetails.region),
+    createData('Availability Zone', cloudInstanceDetails.availability_zone),
+    createData('Public IP', cloudInstanceDetails.public_ips),
+  ];
+
+  const rows2 = [
+    createData('PostgreSQL version', cloudInstanceDetails.db_version),
+    createData('Instance type', cloudInstanceDetails.instance_type),
+  ];
+
+  const rows3 = [
+    createData('Allocated storage', cloudInstanceDetails.storage_size + ' GiB'),
+  ];
+
+  const rows4 = [
+    createData('Username', cloudDBDetails.db_username),
+    createData('Password', 'xxxxxxx'),
+  ];
+
+  return [rows1, rows2, rows3, rows4];
+}
\ No newline at end of file
diff --git a/web/pgadmin/misc/cloud/static/js/azure_schema.ui.js b/web/pgadmin/misc/cloud/static/js/azure_schema.ui.js
new file mode 100644
index 000000000..2419aaebb
--- /dev/null
+++ b/web/pgadmin/misc/cloud/static/js/azure_schema.ui.js
@@ -0,0 +1,495 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2022, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import gettext from 'sources/gettext';
+import url_for from 'sources/url_for';
+import BaseUISchema from 'sources/SchemaView/base_schema.ui';
+import { isEmptyString } from 'sources/validators';
+import getApiInstance from '../../../../static/js/api_instance';
+import {MESSAGE_TYPE } from '../../../../static/js/components/FormComponents';
+import { CloudWizardEventsContext } from './CloudWizard';
+import React from 'react';
+
+
+class AzureCredSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, initValues = {}) {
+    super({
+      oid: null,
+      auth_type: 'interactive_browser_credential',
+      azure_tenant_id: '',
+      azure_subscription_id: '',
+      ...initValues
+    });
+
+    this.fieldOptions = {
+      ...fieldOptions,
+    };
+
+    this.eventBus = React.useContext(CloudWizardEventsContext);
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  validate(state, setError){
+    let isError = false;
+    if (state.cloud_type == 'interactive_browser_credential' && state.azure_tenant_id == ''){
+      isError = true;
+      setError('azure_tenant_id', 'Azure Tenant Id is required for Azure interactive authentication.');
+    }
+    return isError;
+  }
+
+  authenticateAzure = (auth_type, azure_tenant_id) => {
+    let loading_icon_url = url_for(
+      'static', { 'filename': 'img/loading.gif'}
+    );
+    const axiosApi = getApiInstance();
+    this.eventBus.fireEvent('SET_ERROR_MESSAGE_FOR_CLOUD_WIZARD', [MESSAGE_TYPE.INFO, 'Microsoft Azure authentication process is in progress..<img src="' + loading_icon_url + '" alt="' + gettext('Loading...') + '">']);
+    let _url = url_for('azure.verify_credentials');
+    const post_data = {
+      cloud: 'azure',
+      secret: {'auth_type':auth_type, 'azure_tenant_id':azure_tenant_id}
+    };
+    axiosApi.post(_url, post_data)
+      .then((res) => {
+        if (res.data && res.data.success == 1 ) {
+          this.eventBus.fireEvent('SET_ERROR_MESSAGE_FOR_CLOUD_WIZARD',[MESSAGE_TYPE.SUCCESS, 'Authentication completed successfully. Click the Next button to proceed.']);
+          this.eventBus.fireEvent('SET_CRED_VERIFICATION_INITIATED',true);
+        }
+        else if (res.data && res.data.success == 0) {
+          this.eventBus.fireEvent('SET_ERROR_MESSAGE_FOR_CLOUD_WIZARD',[MESSAGE_TYPE.ERROR, res.data.errormsg]);
+          this.eventBus.fireEvent('SET_CRED_VERIFICATION_INITIATED',false);
+        }
+      })
+      .catch((error) => {
+        this.eventBus.fireEvent('SET_ERROR_MESSAGE_FOR_CLOUD_WIZARD',[MESSAGE_TYPE.ERROR, gettext(`Error while verification Microsoft Azure: ${error.response.data.errormsg}`)]);
+      });
+  };
+
+  get baseFields() {
+    let obj = this;
+    return [
+      {
+        id: 'auth_type', label: gettext('Authenticate via'), type: 'toggle',
+        mode: ['create'],
+        options: [
+          {'label': gettext('Azure CLI'), 'value': 'azure_cli_credential'},
+          {'label': gettext('Interactive Browser'), 'value': 'interactive_browser_credential'},
+        ], noEmpty: true,
+        helpMessage: gettext('"Azure CLI"  will use the Azure CLIs currently logged in identity."Interactive Browser" opens a browser to interactively authenticate a user.')
+      },
+      {
+        id: 'azure_tenant_id', label: gettext('Azure Tenant Id'), type: 'text',
+        mode: ['create'], deps: ['auth_type'],
+        helpMessage: gettext('Enter Azure tenant id agianse which user is authenticated.'),
+        disabled: (state) => { return state.auth_type == 'interactive_browser_credential'? false : true;},
+        depChange: (state)=>{
+          if (state.auth_type == 'azure_cli_credential'){
+            state.azure_tenant_id = '';
+          }
+          this.eventBus.fireEvent('SET_CRED_VERIFICATION_INITIATED',false);
+        }
+      },{
+        id:'auth_btn',
+        mode:['create'], deps: ['auth_type', 'azure_tenant_id'],
+        btnName:'Click here to authenticate yourself to Microsoft Azure',
+        type:(state)=>{
+          return{
+            type: 'button',
+            onClick:()=> {obj.authenticateAzure(state.auth_type, state.azure_tenant_id);},
+          };
+        },
+        helpMessage: gettext('By clicking the below button, you will be redirected to the Microsoft Azure authentication page in a new tab if Authentication Via Interactive Browser option is selected.'),
+        disabled: (state) => {return state.auth_type == 'interactive_browser_credential' && state.azure_tenant_id == '' ? true : false;}
+      }
+    ];
+  }
+}
+
+class AzureProjectDetailsSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, initValues={}) {
+    super({
+      oid: undefined,
+      subscription: '',
+      new_resource_group: false,
+      resource_group: '',
+      regions:'',
+      availability_zones:'',
+      ...initValues
+    });
+
+    this.fieldOptions = {
+      ...fieldOptions,
+    };
+
+    this.initValues = initValues;
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    return [
+      {
+        id: 'subscription', label: gettext('Subscription'),
+        mode: ['create'],noEmpty: true,
+        type: () => {
+          return {
+            type: 'select',
+            options: this.fieldOptions.subscriptions,
+            controlProps: {
+              allowClear: false,
+              filter: (options) => {
+                if (options.length == 0) return;
+                let _options = [];
+                options.forEach((option) => {
+                  _options.push({
+                    'label': option.subscription_name + ' | ' + option.subscription_id,
+                    'value': option.subscription_id
+                  });
+                });
+                return _options;
+              },
+            }
+
+          };
+        },
+      },{
+        id: 'resource_group', label: gettext('Resource Group'),
+        mode: ['create'], deps: ['subscription'],
+        noEmpty: true,
+        type: (state) => {
+          return {
+            type: 'select',
+            options: state.subscription ? ()=>this.fieldOptions.resourceGroups(state.subscription) : [],
+            optionsReloadBasis: state.subscription,
+            controlProps: {
+              creatable: true,
+              allowClear: false
+            }
+          };
+        }
+      },{
+        id: 'region', label: gettext('Location'),
+        mode: ['create'], deps: ['subscription'],
+        noEmpty: true,
+        type: (state) => {
+          return {
+            type: 'select',
+            options: state.subscription ? ()=>this.fieldOptions.regions(state.subscription) : [],
+            optionsReloadBasis: state.subscription,
+            allowClear: false
+          };
+        },
+      },{
+        id: 'availability_zone', label: gettext('Availability Zone'),
+        deps:['region'], noEmpty: true,allowClear: false,
+        type: (state) => {
+          return {
+            type: 'select',
+            options:  state.region ? ()=>this.fieldOptions.availabilityZones(state.region) : [],
+            optionsReloadBasis: state.region
+          };
+        },
+      },
+    ];
+  }
+}
+
+class AzureInstanceSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, initValues={}) {
+    super({
+      db_version: '',
+      instance_type: '',
+      storage_size:''
+    });
+
+    this.fieldOptions = {
+      ...fieldOptions,
+    };
+
+    this.initValues = initValues;
+  }
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    return [{
+      id: 'db_version', label: gettext('Database version'),
+      deps:['availability_zone'],noEmpty: true,
+      type: (state) => {
+        return {
+          type: 'select',
+          options: state.availability_zone ? ()=>this.fieldOptions.versionOptions(state.availability_zone) : [],
+          optionsReloadBasis: state.availability_zone
+        };
+      },
+    },{
+      id: 'db_instance_class', label: gettext('Instance class'),
+      type: 'toggle',
+      options: [
+        {'label': gettext('Burstable (1-2 vCores) '), value: 'Burstable'},
+        {'label': gettext('General Purpose (2-64 vCores)'), value: 'GeneralPurpose'},
+        {'label': gettext('Memory Optimized (2-64 vCores)'), value: 'MemoryOptimized'},
+      ],  noEmpty: true, orientation: 'vertical',
+    },{
+      id: 'instance_type', label: gettext('Instance type'),
+      deps: ['db_version', 'db_instance_class'],noEmpty: true,
+      type: (state) => {
+        return {
+          type: 'select',
+          options: ()=> state.db_version ? this.fieldOptions.instanceOptions(state.db_version, state.availability_zone):[],
+          optionsReloadBasis: state.db_version + (state.db_instance_class || 'Burstable'),
+          controlProps: {
+            allowClear: false,
+            filter: (options) => {
+              if (options.length == 0) return;
+              if (state.db_instance_class === undefined) return;
+              let _options = [];
+              options.forEach((option) => {
+                if (option.type == state.db_instance_class){
+                  _options.push({
+                    'label': option.label,
+                    'value': option.value
+                  });
+                }
+              });
+              return _options;
+            },
+          }
+        };
+      },
+    },
+    {
+      id: 'storage_size', label: gettext('Storage Size'),
+      deps: ['db_version', 'db_instance_class'],
+      type: (state) => {
+        return {
+          type: 'select',
+          options: ()=> state.db_version ? this.fieldOptions.storageOptions(state.db_version, state.availability_zone):[],
+          optionsReloadBasis: state.db_version + (state.db_instance_class || 'Burstable'),
+          controlProps: {
+            allowClear: false,
+            filter: (options) => {
+              if (options.length == 0 || state.db_instance_class === undefined) return;
+              let _options = [];
+              options.forEach((option) => {
+                if (option.type == state.db_instance_class){
+                  _options.push({
+                    'label': option.label,
+                    'value': option.value
+                  });
+                }
+              });
+              return _options;
+            },
+          }
+        };
+      },
+      noEmpty: true,
+    }
+    ];
+  }
+}
+
+class AzureDatabaseSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, initValues={}) {
+    super({
+      oid: undefined,
+      gid: undefined,
+      db_name: '',
+      db_username: '',
+      db_password: '',
+      db_confirm_password: '',
+      ...initValues,
+    });
+
+    this.fieldOptions = {
+      ...fieldOptions,
+    };
+
+  }
+
+  validate(data, setErrMsg) {
+    if(!isEmptyString(data.db_username)){
+      if( data.db_username.length > 1 && data.db_username.length > 63){
+        setErrMsg('db_username', 'Admin username must be more than 1 character & less than 63.');
+        return true;
+      }
+
+      if(!(/^[A-Za-z0-9]*$/.test(data.db_username))){
+        setErrMsg('db_username', 'Admin username must only contain characters and numbers.');
+        return true;
+      }
+
+      if(['azure_superuser', 'azure_pg_admin', 'admin', 'administrator', 'root', 'guest', 'public'].includes(data.db_username) || data.db_username.startsWith('pg_')){
+        setErrMsg('db_username', 'Specified Admin username is not allowed');
+        return true;
+      }
+    }
+
+    if(!isEmptyString(data.db_password) && !isEmptyString(data.db_confirm_password)
+    && data.db_password != data.db_confirm_password) {
+      setErrMsg('db_confirm_password', gettext('Passwords do not match.'));
+      return true;
+    }
+    if (!isEmptyString(data.db_confirm_password) && data.db_confirm_password.length < 8) {
+      setErrMsg('db_confirm_password', gettext('Password must be 8 characters or more.'));
+      return true;
+    }
+    if (data.db_confirm_password.includes('\'') || data.db_confirm_password.includes('"') ||
+    data.db_confirm_password.includes('@') || data.db_confirm_password.includes('/')) {
+      setErrMsg('db_confirm_password', gettext('Invalid passowrd.'));
+      return true;
+    }
+
+    return false;
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    return [{
+      id: 'gid', label: gettext('Server group'), type: 'select',
+      options: this.fieldOptions.server_groups,
+      mode: ['create'],
+      controlProps: { allowClear: false },
+      noEmpty: true,
+    },{
+      id: 'db_username', label: gettext('Admin username'),
+      type: 'text',
+      mode: ['create'], noEmpty: true,
+      helpMessage: gettext('Admin username must be 1-63 characters and can only contain characters and numbers.Username cannot be "\azure_superuser"\, "\azure_pg_admin\", "\admin\", "\administrator\", "\root\", "\guest\", "\public\" or start with "\pg_\".')
+    }, {
+      id: 'db_password', label: gettext('Password'), type: 'password',
+      mode: ['create'], noEmpty: true,
+      helpMessage: gettext('Password must be 8-128 characters and must contain characters from three of the following categories – English uppercase letters, English lowercase letters, numbers (0-9), and non-alphanumeric characters (!, $, #, %, etc.) and cannot contain all or part of the login name.')
+    }, {
+      id: 'db_confirm_password', label: gettext('Confirm password'),
+      type: 'password',
+      mode: ['create'], noEmpty: true,
+    }];
+  }
+}
+
+class AzureNetworkSchema extends BaseUISchema {
+  constructor() {
+    super();
+  }
+
+  get baseFields() {
+    return [
+      {
+        id: 'public_ips', label: gettext('Public IP range'), type: 'text',
+        mode: ['create'],
+        helpMessage: gettext('List of IP Addresses/ range of IP Addresess (start IP Address - end IP address) for permitting the inbound traffic.Add multiple ip addresses/ranges by comma separated. Ex: 127.0.0.1, 127.0.0.1 - 127.0.0.4. Add 0.0.0.0 - 255.255.255.255 for publically accessible.'),
+      },
+    ];
+  }
+}
+
+class AzureClusterSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, initValues = {}) {
+    super({
+      oid: undefined,
+      name: '',
+      // Need to initilize child class init values in parent class itself
+      public_ips: initValues?.hostIP.split('/')[0],
+      db_instance_class: 'Burstable',
+      ...initValues
+    });
+
+    this.fieldOptions = {
+      ...fieldOptions,
+    };
+    this.initValues = initValues;
+
+    this.eventBus = React.useContext(CloudWizardEventsContext);
+
+    this.azureProjectDetails = new AzureProjectDetailsSchema({
+      subscriptions: this.fieldOptions.subscriptions,
+      resourceGroups: this.fieldOptions.resourceGroups,
+      regions: this.fieldOptions.regions,
+      availabilityZones: this.fieldOptions.availabilityZones,
+    },{});
+
+    this.azureInstanceDetails = new AzureInstanceSchema({
+      versionOptions: this.fieldOptions.versionOptions,
+      instanceOptions: this.fieldOptions.instanceOptions,
+      storageOptions: this.fieldOptions.storageOptions
+    },{});
+
+    this.azureNetworkSchema = new AzureNetworkSchema({},
+      {});
+  }
+
+  validate (data, setErr) {
+    if (!isEmptyString(data.name) && (/[A-Z]/.test(data.name)  || data.name.length < 3)) {
+      setErr('name', gettext('Name must be more than 3 characters or more & Shoudld not have capital letter'));
+      return true;
+    }
+
+    let _url = url_for('azure.check_cluster_name_availability');
+    const post_data = {
+      name: data.name,
+    };
+    const axiosApi = getApiInstance();
+    axiosApi.post(_url, post_data)
+      .then((res) => {
+        if (res.data && res.data.success == 0 ) {
+          setErr('name', gettext('Cluster name is already is use.'));
+          return true;
+        }
+      })
+      .catch((error) => {
+        this.eventBus.fireEvent('SET_ERROR_MESSAGE_FOR_CLOUD_WIZARD',[MESSAGE_TYPE.ERROR, gettext(`Error while chekcing server name availability with Microsoft Azure: ${error.response.data.errormsg}`)]);
+      });
+    return false;
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    return [
+      {
+        id: 'name', label: gettext('Cluster name'), type: 'text',
+        mode: ['create'], noEmpty: true
+      },
+      {
+        type: 'nested-fieldset', label: gettext('Project Details'),
+        mode: ['create'],
+        schema: this.azureProjectDetails,
+      },
+      {
+        type: 'nested-fieldset', label: gettext('Version & Instance'),
+        mode: ['create'],
+        schema:this.azureInstanceDetails
+      },
+      {
+        type: 'nested-fieldset', label: gettext('Network Connectivity'),
+        mode: ['create'],
+        schema: this.azureNetworkSchema
+      }
+    ];
+  }
+}
+
+export {
+  AzureCredSchema,
+  AzureClusterSchema,
+  AzureDatabaseSchema
+};
\ No newline at end of file
diff --git a/web/pgadmin/misc/cloud/static/js/cloud.js b/web/pgadmin/misc/cloud/static/js/cloud.js
index 22f74ce6d..ac1711fd8 100644
--- a/web/pgadmin/misc/cloud/static/js/cloud.js
+++ b/web/pgadmin/misc/cloud/static/js/cloud.js
@@ -10,6 +10,7 @@ import React from 'react';
 import ReactDOM from 'react-dom';
 import Theme from 'sources/Theme';
 import CloudWizard from './CloudWizard';
+import getApiInstance from '../../../../static/js/api_instance';
 
 
 // Cloud Wizard
@@ -124,6 +125,15 @@ define('pgadmin.misc.cloud', [
             hooks: {
               // Triggered when the dialog is closed
               onclose: function () {
+                if(event.target instanceof Object){
+                  const axiosApi = getApiInstance();
+                  let _url = url_for('cloud.clear_cloud_session');
+                  axiosApi.post(_url)
+                    .then(() => {})
+                    .catch((error) => {
+                      Alertify.error(gettext(`Error while clearing cloud wizard data: ${error.response.data.errormsg}`));
+                    });
+                }
                 // Clear the view and remove the react component.
                 return setTimeout((function () {
                   ReactDOM.unmountComponentAtNode(document.getElementById('cloudWizardDlg'));
diff --git a/web/pgadmin/misc/cloud/static/js/cloud_components.jsx b/web/pgadmin/misc/cloud/static/js/cloud_components.jsx
index 742c402b7..de0a56b8b 100644
--- a/web/pgadmin/misc/cloud/static/js/cloud_components.jsx
+++ b/web/pgadmin/misc/cloud/static/js/cloud_components.jsx
@@ -14,6 +14,7 @@ import { DefaultButton, PrimaryButton } from '../../../../static/js/components/B
 import { makeStyles } from '@material-ui/core/styles';
 import PropTypes from 'prop-types';
 import { getAWSSummary } from './aws';
+import  {getAzureSummary} from './azure';
 import { getBigAnimalSummary } from './biganimal';
 import { commonTableStyles } from '../../../../static/js/Theme';
 import { Table, TableBody, TableCell, TableHead, TableRow } from '@material-ui/core';
@@ -70,7 +71,9 @@ export function FinalSummary(props) {
   if (props.cloudProvider == 'biganimal') {
     summary = getBigAnimalSummary(props.cloudProvider, props.instanceData, props.databaseData);
     summaryHeader[1] = 'Version Details';
-  } else {
+  } else if(props.cloudProvider == 'azure'){
+    summary = getAzureSummary(props.cloudProvider, props.instanceData, props.databaseData);
+  }else {
     summary = getAWSSummary(props.cloudProvider, props.instanceData, props.databaseData);
   }
 
diff --git a/web/pgadmin/misc/cloud/utils/__init__.py b/web/pgadmin/misc/cloud/utils/__init__.py
index abaa92283..6d91ad8c3 100644
--- a/web/pgadmin/misc/cloud/utils/__init__.py
+++ b/web/pgadmin/misc/cloud/utils/__init__.py
@@ -20,10 +20,10 @@ def get_my_ip():
     """ Return the public IP of this host """
     http = urllib3.PoolManager()
     try:
-        external_ip = http.request('GET', 'http://ident.me').data
+        external_ip = http.request('GET', 'http://ifconfig.me/ip').data
     except Exception:
         try:
-            external_ip = http.request('GET', 'http://ifconfig.me/ip').data
+            external_ip = http.request('GET', 'http://ident.me').data
         except Exception:
             external_ip = '127.0.0.1'
 
diff --git a/web/pgadmin/static/img/azure.svg b/web/pgadmin/static/img/azure.svg
new file mode 100644
index 000000000..445315a5d
--- /dev/null
+++ b/web/pgadmin/static/img/azure.svg
@@ -0,0 +1 @@
+<svg height="2359" width="2500" xmlns="http://www.w3.org/2000/svg" viewBox="-0.4500000000000005 0.38 800.8891043012813 754.2299999999999"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="353.1" x2="107.1" y1="56.3" y2="783"><stop offset="0" stop-color="#114a8b"/><stop offset="1" stop-color="#0669bc"/></linearGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="429.8" x2="372.9" y1="394.9" y2="414.2"><stop offset="0" stop-opacity=".3"/><stop offset=".1" stop-opacity=".2"/><stop offset=".3" stop-opacity=".1"/><stop offset=".6" stop-opacity=".1"/><stop offset="1" stop-opacity="0"/></linearGradient><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="398.4" x2="668.4" y1="35.1" y2="754.4"><stop offset="0" stop-color="#3ccbf4"/><stop offset="1" stop-color="#2892df"/></linearGradient><path d="M266.71.4h236.71L257.69 728.9a37.8 37.8 0 0 1-5.42 10.38c-2.33 3.16-5.14 5.93-8.33 8.22s-6.71 4.07-10.45 5.27-7.64 1.82-11.56 1.82H37.71c-5.98 0-11.88-1.42-17.2-4.16A37.636 37.636 0 0 1 7.1 738.87a37.762 37.762 0 0 1-6.66-16.41c-.89-5.92-.35-11.97 1.56-17.64L230.94 26.07c1.25-3.72 3.08-7.22 5.42-10.38 2.33-3.16 5.15-5.93 8.33-8.22 3.19-2.29 6.71-4.07 10.45-5.27S262.78.38 266.7.38v.01z" fill="url(#a)"/><path d="M703.07 754.59H490.52c-2.37 0-4.74-.22-7.08-.67-2.33-.44-4.62-1.1-6.83-1.97s-4.33-1.95-6.34-3.21a38.188 38.188 0 0 1-5.63-4.34l-241.2-225.26a17.423 17.423 0 0 1-5.1-8.88 17.383 17.383 0 0 1 7.17-18.21c2.89-1.96 6.3-3.01 9.79-3.01h375.36l92.39 265.56z" fill="#0078d4"/><path d="M504.27.4l-165.7 488.69 270.74-.06 92.87 265.56H490.43c-2.19-.02-4.38-.22-6.54-.61s-4.28-.96-6.34-1.72a38.484 38.484 0 0 1-11.36-6.51L303.37 593.79l-45.58 134.42c-1.18 3.36-2.8 6.55-4.82 9.48a40.479 40.479 0 0 1-16.05 13.67 40.03 40.03 0 0 1-10.13 3.23H37.82c-6.04.02-12-1.42-17.37-4.2A37.664 37.664 0 0 1 .43 722a37.77 37.77 0 0 1 1.87-17.79L230.87 26.58c1.19-3.79 2.98-7.36 5.3-10.58 2.31-3.22 5.13-6.06 8.33-8.4s6.76-4.16 10.53-5.38S262.75.38 266.72.4h237.56z" fill="url(#b)"/><path d="M797.99 704.82a37.847 37.847 0 0 1 1.57 17.64 37.867 37.867 0 0 1-6.65 16.41 37.691 37.691 0 0 1-30.61 15.72H498.48c5.98 0 11.88-1.43 17.21-4.16 5.32-2.73 9.92-6.7 13.41-11.56s5.77-10.49 6.66-16.41.35-11.97-1.56-17.64L305.25 26.05a37.713 37.713 0 0 0-13.73-18.58c-3.18-2.29-6.7-4.06-10.43-5.26S273.46.4 269.55.4h263.81c3.92 0 7.81.61 11.55 1.81 3.73 1.2 7.25 2.98 10.44 5.26 3.18 2.29 5.99 5.06 8.32 8.21s4.15 6.65 5.41 10.37l228.95 678.77z" fill="url(#c)"/></svg>
\ No newline at end of file
diff --git a/web/pgadmin/static/js/SchemaView/MappedControl.jsx b/web/pgadmin/static/js/SchemaView/MappedControl.jsx
index 4a0f26746..0cfd3abaa 100644
--- a/web/pgadmin/static/js/SchemaView/MappedControl.jsx
+++ b/web/pgadmin/static/js/SchemaView/MappedControl.jsx
@@ -12,7 +12,7 @@ import _ from 'lodash';
 import {
   FormInputText, FormInputSelect, FormInputSwitch, FormInputCheckbox, FormInputColor,
   FormInputFileSelect, FormInputToggle, InputSwitch, FormInputSQL, InputSQL, FormNote, FormInputDateTimePicker, PlainString,
-  InputSelect, InputText, InputCheckbox, InputDateTimePicker, InputFileSelect, FormInputKeyboardShortcut, FormInputQueryThreshold, FormInputSelectThemes, InputRadio
+  InputSelect, InputText, InputCheckbox, InputDateTimePicker, InputFileSelect, FormInputKeyboardShortcut, FormInputQueryThreshold, FormInputSelectThemes, InputRadio, FormButton
 } from '../components/FormComponents';
 import Privilege from '../components/Privilege';
 import { evalFunc } from 'sources/utils';
@@ -21,7 +21,7 @@ import CustomPropTypes from '../custom_prop_types';
 import { SelectRefresh } from '../components/SelectRefresh';
 
 /* Control mapping for form view */
-function MappedFormControlBase({ type, value, id, onChange, className, visible, inputRef, noLabel, ...props }) {
+function MappedFormControlBase({ type, value, id, onChange, className, visible, inputRef, noLabel, onClick, ...props }) {
   const name = id;
   const onTextChange = useCallback((e) => {
     let val = e;
@@ -86,6 +86,8 @@ function MappedFormControlBase({ type, value, id, onChange, className, visible,
     return <FormInputQueryThreshold name={name} value={value} onChange={onTextChange} {...props}/>;
   case 'theme':
     return <FormInputSelectThemes name={name} value={value} onChange={onTextChange} {...props}/>;
+  case 'button':
+    return <FormButton name={name} value={value} className={className} onClick={onClick}  {...props} />;
   default:
     return <PlainString value={value} {...props} />;
   }
@@ -103,7 +105,8 @@ MappedFormControlBase.propTypes = {
   ]),
   visible: PropTypes.bool,
   inputRef: CustomPropTypes.ref,
-  noLabel: PropTypes.bool
+  noLabel: PropTypes.bool,
+  onClick: PropTypes.func
 };
 
 /* Control mapping for grid cell view */
@@ -197,11 +200,11 @@ const ALLOWED_PROPS_FIELD_COMMON = [
   'mode', 'value', 'readonly', 'disabled', 'hasError', 'id',
   'label', 'options', 'optionsLoaded', 'controlProps', 'schema', 'inputRef',
   'visible', 'autoFocus', 'helpMessage', 'className', 'optionsReloadBasis',
-  'orientation', 'isvalidate', 'fields', 'radioType', 'hideBrowseButton'
+  'orientation', 'isvalidate', 'fields', 'radioType', 'hideBrowseButton', 'btnName'
 ];
 
 const ALLOWED_PROPS_FIELD_FORM = [
-  'type', 'onChange', 'state', 'noLabel', 'text',
+  'type', 'onChange', 'state', 'noLabel', 'text','onClick'
 ];
 
 const ALLOWED_PROPS_FIELD_CELL = [
diff --git a/web/pgadmin/static/js/SchemaView/index.jsx b/web/pgadmin/static/js/SchemaView/index.jsx
index ca8ed1f4b..4e6fbeacb 100644
--- a/web/pgadmin/static/js/SchemaView/index.jsx
+++ b/web/pgadmin/static/js/SchemaView/index.jsx
@@ -485,6 +485,10 @@ function SchemaDialogView({
     setDirty(isDataChanged);
 
     /* tell the callbacks the data has changed */
+    if(viewHelperProps.mode !== 'edit') {
+      /* If new then merge the changed data with origData */
+      changedData = _.assign({}, schema.origData, changedData);
+    }
     props.onDataChange && props.onDataChange(isDataChanged, changedData);
   }, [sessData, formReady]);
 
@@ -597,9 +601,8 @@ function SchemaDialogView({
     setLoaderText('Saving...');
     /* Get the changed data */
     let changeData = getChangedData(schema, viewHelperProps, sessData);
-
     /* Add the id when in edit mode */
-    if(viewHelperProps.mode !== 'edit') {
+    if(viewHelperProps.mode !== 'edit'){
       /* If new then merge the changed data with origData */
       changeData = _.assign({}, schema.origData, changeData);
     } else {
diff --git a/web/pgadmin/static/js/components/ExternalIcon.jsx b/web/pgadmin/static/js/components/ExternalIcon.jsx
index 13e986201..b5c0fee90 100644
--- a/web/pgadmin/static/js/components/ExternalIcon.jsx
+++ b/web/pgadmin/static/js/components/ExternalIcon.jsx
@@ -16,6 +16,7 @@ import Expand from '../../img/fonticon/open_in_full.svg?svgr';
 import Collapse from '../../img/fonticon/close_fullscreen.svg?svgr';
 import AWS from '../../img/aws.svg?svgr';
 import BigAnimal from '../../img/biganimal.svg?svgr';
+import Azure from '../../img/azure.svg?svgr';
 
 export default function ExternalIcon({Icon, ...props}) {
   return <Icon className={'MuiSvgIcon-root'} {...props} />;
@@ -72,3 +73,6 @@ AWSIcon.propTypes = {style: PropTypes.object};
 
 export const BigAnimalIcon = ({style})=><ExternalIcon Icon={BigAnimal} style={{height: '1.4rem', ...style}} data-label="BigAnimalIcon" />;
 BigAnimalIcon.propTypes = {style: PropTypes.object};
+
+export const AzureIcon = ({style})=><ExternalIcon Icon={Azure} style={{height: '1.4rem', ...style}} data-label="AzureIcon" />;
+AzureIcon.propTypes = {style: PropTypes.object};
\ No newline at end of file
diff --git a/web/pgadmin/static/js/components/FormComponents.jsx b/web/pgadmin/static/js/components/FormComponents.jsx
index 28812238a..0f85d0fe0 100644
--- a/web/pgadmin/static/js/components/FormComponents.jsx
+++ b/web/pgadmin/static/js/components/FormComponents.jsx
@@ -1289,3 +1289,22 @@ NotifierMessage.propTypes = {
   closable: PropTypes.bool,
   onClose: PropTypes.func,
 };
+
+
+export function FormButton({required, label,
+  className, helpMessage, onClick, disabled, ...props }) {
+  return (
+    <FormInput required={required} label={label} className={className}  helpMessage={helpMessage}>
+      <PrimaryButton onClick={onClick} disabled={disabled} >{gettext(props.btnName)}</PrimaryButton>
+    </FormInput>
+  );
+}
+FormButton.propTypes = {
+  required: PropTypes.bool,
+  label: PropTypes.string,
+  className: CustomPropTypes.className,
+  helpMessage: PropTypes.string,
+  onClick: PropTypes.func,
+  disabled: PropTypes.bool,
+  btnName: PropTypes.string
+};
