示例#1
0
 def set_token(self):
     import traceback
     from azure.cli.core.azclierror import AzureConnectionError, AzureResponseError
     try:
         super(MSIAuthenticationWrapper, self).set_token()
     except requests.exceptions.ConnectionError as err:
         logger.debug('throw requests.exceptions.ConnectionError when doing MSIAuthentication: \n%s',
                      traceback.format_exc())
         raise AzureConnectionError('Failed to connect to MSI. Please make sure MSI is configured correctly '
                                    'and check the network connection.\nError detail: {}'.format(str(err)))
     except requests.exceptions.HTTPError as err:
         logger.debug('throw requests.exceptions.HTTPError when doing MSIAuthentication: \n%s',
                      traceback.format_exc())
         try:
             raise AzureResponseError('Failed to connect to MSI. Please make sure MSI is configured correctly.\n'
                                      'Get Token request returned http error: {}, reason: {}'
                                      .format(err.response.status, err.response.reason))
         except AttributeError:
             raise AzureResponseError('Failed to connect to MSI. Please make sure MSI is configured correctly.\n'
                                      'Get Token request returned: {}'.format(err.response))
     except TimeoutError as err:
         logger.debug('throw TimeoutError when doing MSIAuthentication: \n%s',
                      traceback.format_exc())
         raise AzureConnectionError('MSI endpoint is not responding. Please make sure MSI is configured correctly.\n'
                                    'Error detail: {}'.format(str(err)))
示例#2
0
def resolve_store_metadata(cmd, config_store_name):
    resource_group = None
    endpoint = None
    try:
        config_store_client = cf_configstore(cmd.cli_ctx)
        all_stores = config_store_client.list()
        for store in all_stores:
            if store.name.lower() == config_store_name.lower():
                if resource_group is None:
                    # Id has a fixed structure /subscriptions/subscriptionName/resourceGroups/groupName/providers/providerName/configurationStores/storeName"
                    resource_group = store.id.split('/')[4]
                    endpoint = store.endpoint
                else:
                    raise ValidationError(
                        'Multiple configuration stores found with name {}.'.
                        format(config_store_name))
    except HttpResponseError as ex:
        raise AzureResponseError(
            "Failed to get the list of App Configuration stores for the current user. Make sure that the account that logged in has sufficient permissions to access the App Configuration store.\n{}"
            .format(str(ex)))

    if resource_group is not None and endpoint is not None:
        return resource_group, endpoint

    raise ResourceNotFoundError(
        "Failed to find the App Configuration store '{}'.".format(
            config_store_name))
示例#3
0
def resolve_deleted_store_metadata(cmd,
                                   config_store_name,
                                   resource_group_name=None,
                                   location=None):
    resource_group = None
    metadata_location = None
    try:
        client = cf_configstore(cmd.cli_ctx)
        deleted_stores = client.list_deleted()
        for deleted_store in deleted_stores:
            # configuration_store_id has a fixed structure /subscriptions/subscription_id/resourceGroups/resource_group_name/providers/Microsoft.AppConfiguration/configurationStores/configuration_store_name
            metadata_resource_group = deleted_store.configuration_store_id.split(
                '/')[4]
            # match the name and additionally match resource group and location if available.
            if deleted_store.name.lower() == config_store_name.lower() and (
                    resource_group_name is None or resource_group_name.lower()
                    == metadata_resource_group.lower()
            ) and (location is None or location == deleted_store.location):
                if metadata_location is None:
                    resource_group = metadata_resource_group
                    metadata_location = deleted_store.location
                else:
                    # It should reach here only when the user has provided only name. If they provide either location or resource group, we should be able to uniquely find the store.
                    raise ValidationError(
                        'Multiple configuration stores found with name {}.'.
                        format(config_store_name))
    except HttpResponseError as ex:
        raise AzureResponseError(
            "Failed to get the list of deleted App Configuration stores for the current user. Make sure that the account that logged in has sufficient permissions to access the App Configuration store.\n{}"
            .format(str(ex)))

    if resource_group is not None and metadata_location is not None:
        return resource_group, metadata_location

    raise ResourceNotFoundError(
        "Failed to find the deleted App Configuration store '{}'. If you think that the store name is correct, please validate all your input parameters again."
        .format(config_store_name))
示例#4
0
def map_azure_error_to_cli_error(azure_error):
    error_message = getattr(azure_error, "message", str(azure_error))
    if isinstance(azure_error, HttpResponseError):
        status_code = getattr(azure_error, "status_code", None)
        if status_code:
            status_code = int(status_code)
            if status_code == 400:
                return BadRequestError(error_message)
            if status_code == 401:
                return UnauthorizedError(error_message)
            if status_code == 403:
                return ForbiddenError(error_message)
            if status_code == 404:
                return ResourceNotFoundError(error_message)
            if 400 <= status_code < 500:
                return UnclassifiedUserFault(error_message)
            if 500 <= status_code < 600:
                return AzureInternalError(error_message)
        return ServiceError(error_message)
    if isinstance(azure_error, ServiceRequestError):
        return ClientRequestError(error_message)
    if isinstance(azure_error, ServiceResponseError):
        return AzureResponseError(error_message)
    return ServiceError(error_message)
示例#5
0
def upload_blob(cmd,
                client,
                file_path=None,
                container_name=None,
                blob_name=None,
                blob_type=None,
                metadata=None,
                validate_content=False,
                maxsize_condition=None,
                max_connections=2,
                lease_id=None,
                if_modified_since=None,
                if_unmodified_since=None,
                if_match=None,
                if_none_match=None,
                timeout=None,
                progress_callback=None,
                encryption_scope=None,
                overwrite=None,
                data=None,
                length=None,
                **kwargs):
    """Upload a blob to a container."""
    from azure.core.exceptions import ResourceExistsError
    upload_args = {
        'blob_type': transform_blob_type(cmd, blob_type),
        'lease': lease_id,
        'max_concurrency': max_connections
    }

    if overwrite is not None:
        upload_args['overwrite'] = overwrite
    if maxsize_condition:
        upload_args['maxsize_condition'] = maxsize_condition

    if cmd.supported_api_version(min_api='2016-05-31'):
        upload_args['validate_content'] = validate_content

    if progress_callback:
        upload_args['raw_response_hook'] = progress_callback

    check_blob_args = {
        'lease': lease_id,
        'if_modified_since': if_modified_since,
        'if_unmodified_since': if_unmodified_since,
        'if_match': if_match,
        'if_none_match': if_none_match,
        'timeout': timeout
    }

    # used to check for the preconditions as upload_append_blob() cannot
    if blob_type == 'append':
        if client.exists(timeout=timeout):
            client.get_blob_properties(**check_blob_args)

    # Because the contents of the uploaded file may be too large, it should be passed into the a stream object,
    # upload_blob() read file data in batches to avoid OOM problems
    try:
        if file_path:
            length = os.path.getsize(file_path)
            with open(file_path, 'rb') as stream:
                response = client.upload_blob(
                    data=stream,
                    length=length,
                    metadata=metadata,
                    encryption_scope=encryption_scope,
                    **upload_args,
                    **kwargs)
        if data is not None:
            response = client.upload_blob(data=data,
                                          length=length,
                                          metadata=metadata,
                                          encryption_scope=encryption_scope,
                                          **upload_args,
                                          **kwargs)
    except ResourceExistsError as ex:
        from azure.cli.core.azclierror import AzureResponseError
        raise AzureResponseError(
            "{}\nIf you want to overwrite the existing one, please add --overwrite in your command."
            .format(ex.message))

    # PageBlobChunkUploader verifies the file when uploading the chunk data, If the contents of the file are
    # all null byte("\x00"), the file will not be uploaded, and the response will be none.
    # Therefore, the compatibility logic for response is added to keep it consistent with track 1
    if response is None:
        return {"etag": None, "lastModified": None}

    from msrest import Serializer
    if 'content_md5' in response and response['content_md5'] is not None:
        response['content_md5'] = Serializer.serialize_bytearray(
            response['content_md5'])
    if 'content_crc64' in response and response['content_crc64'] is not None:
        response['content_crc64'] = Serializer.serialize_bytearray(
            response['content_crc64'])
    return response
示例#6
0
def arm_exception_handler(ex, fault_type, summary, return_if_not_found=False):
    if isinstance(ex, AuthenticationError):
        telemetry.set_exception(exception=ex,
                                fault_type=fault_type,
                                summary=summary)
        raise AzureResponseError(
            "Authentication error occured while making ARM request: " +
            str(ex) + "\nSummary: {}".format(summary))

    if isinstance(ex, TokenExpiredError):
        telemetry.set_exception(exception=ex,
                                fault_type=fault_type,
                                summary=summary)
        raise AzureResponseError(
            "Token expiration error occured while making ARM request: " +
            str(ex) + "\nSummary: {}".format(summary))

    if isinstance(ex, HttpOperationError):
        status_code = ex.response.status_code
        if status_code == 404 and return_if_not_found:
            return
        if status_code // 100 == 4:
            telemetry.set_user_fault()
        telemetry.set_exception(exception=ex,
                                fault_type=fault_type,
                                summary=summary)
        if status_code // 100 == 5:
            raise AzureInternalError(
                "Http operation error occured while making ARM request: " +
                str(ex) + "\nSummary: {}".format(summary))
        raise AzureResponseError(
            "Http operation error occured while making ARM request: " +
            str(ex) + "\nSummary: {}".format(summary))

    if isinstance(ex, MSRestValidationError):
        telemetry.set_exception(exception=ex,
                                fault_type=fault_type,
                                summary=summary)
        raise AzureResponseError(
            "Validation error occured while making ARM request: " + str(ex) +
            "\nSummary: {}".format(summary))

    if isinstance(ex, HttpResponseError):
        status_code = ex.status_code
        if status_code == 404 and return_if_not_found:
            return
        if status_code // 100 == 4:
            telemetry.set_user_fault()
        telemetry.set_exception(exception=ex,
                                fault_type=fault_type,
                                summary=summary)
        if status_code // 100 == 5:
            raise AzureInternalError(
                "Http response error occured while making ARM request: " +
                str(ex) + "\nSummary: {}".format(summary))
        raise AzureResponseError(
            "Http response error occured while making ARM request: " +
            str(ex) + "\nSummary: {}".format(summary))

    if isinstance(ex, ResourceNotFoundError) and return_if_not_found:
        return

    telemetry.set_exception(exception=ex,
                            fault_type=fault_type,
                            summary=summary)
    raise ClientRequestError("Error occured while making ARM request: " +
                             str(ex) + "\nSummary: {}".format(summary))
示例#7
0
    def Update(self,
               cmd,
               resource_group_name,
               cluster_name,
               auto_upgrade_minor_version,
               release_train,
               version,
               configuration_settings,
               configuration_protected_settings,
               yes=False):
        self.__normalize_config(configuration_settings,
                                configuration_protected_settings)

        # Prompt message to ask customer to confirm again
        if len(configuration_settings) > 0:
            impactScenario = ""
            messageBody = ""
            disableTraining = False
            disableInference = False
            disableNvidiaDevicePlugin = False
            hasAllowInsecureConnections = False
            hasInferenceRouterServiceType = False
            hasInternalLoadBalancerProvider = False
            hasSslCname = False
            hasNodeSelector = False
            enableLogAnalyticsWS = False

            enableTraining = _get_value_from_config_protected_config(
                self.ENABLE_TRAINING, configuration_settings,
                configuration_protected_settings)
            if enableTraining is not None:
                disableTraining = str(enableTraining).lower() == 'false'
                if disableTraining:
                    messageBody = messageBody + "enableTraining from True to False,\n"

            enableInference = _get_value_from_config_protected_config(
                self.ENABLE_INFERENCE, configuration_settings,
                configuration_protected_settings)
            if enableInference is not None:
                disableInference = str(enableInference).lower() == 'false'
                if disableInference:
                    messageBody = messageBody + "enableInference from True to False,\n"

            installNvidiaDevicePlugin = _get_value_from_config_protected_config(
                self.installNvidiaDevicePlugin, configuration_settings,
                configuration_protected_settings)
            if installNvidiaDevicePlugin is not None:
                disableNvidiaDevicePlugin = str(
                    installNvidiaDevicePlugin).lower() == 'false'
                if disableNvidiaDevicePlugin:
                    messageBody = messageBody + "installNvidiaDevicePlugin from True to False if Nvidia GPU is used,\n"

            allowInsecureConnections = _get_value_from_config_protected_config(
                self.allowInsecureConnections, configuration_settings,
                configuration_protected_settings)
            if allowInsecureConnections is not None:
                hasAllowInsecureConnections = True
                messageBody = messageBody + "allowInsecureConnections\n"

            inferenceRouterServiceType = _get_value_from_config_protected_config(
                self.inferenceRouterServiceType, configuration_settings,
                configuration_protected_settings)
            if inferenceRouterServiceType is not None:
                hasInferenceRouterServiceType = True
                messageBody = messageBody + "inferenceRouterServiceType\n"

            internalLoadBalancerProvider = _get_value_from_config_protected_config(
                self.internalLoadBalancerProvider, configuration_settings,
                configuration_protected_settings)
            if internalLoadBalancerProvider is not None:
                hasInternalLoadBalancerProvider = True
                messageBody = messageBody + "internalLoadBalancerProvider\n"

            sslCname = _get_value_from_config_protected_config(
                self.SSL_Cname, configuration_settings,
                configuration_protected_settings)
            if sslCname is not None:
                hasSslCname = True
                messageBody = messageBody + "sslCname\n"

            hasNodeSelector = _check_nodeselector_existed(
                configuration_settings, configuration_protected_settings)
            if hasNodeSelector:
                messageBody = messageBody + "nodeSelector. Update operation can't remove an existed node selector, but can update or add new ones.\n"

            logAnalyticsWS = _get_value_from_config_protected_config(
                self.LOG_ANALYTICS_WS_ENABLED, configuration_settings,
                configuration_protected_settings)
            if logAnalyticsWS is not None:
                enableLogAnalyticsWS = str(logAnalyticsWS).lower() == 'true'
                if enableLogAnalyticsWS:
                    messageBody = messageBody + "To update logAnalyticsWS from False to True, please provide all original configurationProtectedSettings. Otherwise, those settings would be considered obsolete and deleted.\n"

            if disableTraining or disableNvidiaDevicePlugin or hasNodeSelector:
                impactScenario = "jobs"

            if disableInference or disableNvidiaDevicePlugin or hasAllowInsecureConnections or hasInferenceRouterServiceType or hasInternalLoadBalancerProvider or hasNodeSelector or hasSslCname:
                if impactScenario == "":
                    impactScenario = "online endpoints and deployments"
                else:
                    impactScenario = impactScenario + ", online endpoints and deployments"

            if impactScenario != "":
                message = (
                    "\nThe following configuration update will IMPACT your active Machine Learning "
                    + impactScenario +
                    ". It will be the safe update if the cluster doesn't have active Machine Learning "
                    + impactScenario + ".\n\n" + messageBody + "\nProceed?")
                user_confirmation_factory(cmd, yes, message=message)
            else:
                if enableLogAnalyticsWS:
                    message = "\n" + messageBody + "\nProceed?"
                    user_confirmation_factory(cmd, yes, message=message)

        if len(configuration_protected_settings) > 0:
            subscription_id = get_subscription_id(cmd.cli_ctx)

            if self.AZURE_LOG_ANALYTICS_CONNECTION_STRING not in configuration_protected_settings:
                try:
                    _, shared_key = _get_log_analytics_ws_connection_string(
                        cmd, subscription_id, resource_group_name,
                        cluster_name, '', True)
                    configuration_protected_settings[
                        self.
                        AZURE_LOG_ANALYTICS_CONNECTION_STRING] = shared_key
                    logger.info(
                        "Get log analytics connection string succeeded.")
                except azure.core.exceptions.HttpResponseError:
                    logger.info(
                        "Failed to get log analytics connection string.")

            if self.RELAY_SERVER_CONNECTION_STRING not in configuration_protected_settings:
                try:
                    relay_connection_string, _, _ = _get_relay_connection_str(
                        cmd, subscription_id, resource_group_name,
                        cluster_name, '', self.RELAY_HC_AUTH_NAME, True)
                    configuration_protected_settings[
                        self.
                        RELAY_SERVER_CONNECTION_STRING] = relay_connection_string
                    logger.info("Get relay connection string succeeded.")
                except azure.mgmt.relay.models.ErrorResponseException as ex:
                    if ex.response.status_code == 404:
                        raise ResourceNotFoundError(
                            "Relay server not found.") from ex
                    raise AzureResponseError(
                        "Failed to get relay connection string.") from ex

            if self.SERVICE_BUS_CONNECTION_STRING not in configuration_protected_settings:
                try:
                    service_bus_connection_string, _ = _get_service_bus_connection_string(
                        cmd, subscription_id, resource_group_name,
                        cluster_name, '', {}, True)
                    configuration_protected_settings[
                        self.
                        SERVICE_BUS_CONNECTION_STRING] = service_bus_connection_string
                    logger.info("Get service bus connection string succeeded.")
                except azure.core.exceptions.HttpResponseError as ex:
                    if ex.response.status_code == 404:
                        raise ResourceNotFoundError(
                            "Service bus not found.") from ex
                    raise AzureResponseError(
                        "Failed to get service bus connection string.") from ex

            configuration_protected_settings = _dereference(
                self.reference_mapping, configuration_protected_settings)

            if self.sslKeyPemFile in configuration_protected_settings and \
                    self.sslCertPemFile in configuration_protected_settings:
                logger.info(
                    f"Both {self.sslKeyPemFile} and {self.sslCertPemFile} are set, update ssl key."
                )
                fe_ssl_cert_file = configuration_protected_settings.get(
                    self.sslCertPemFile)
                fe_ssl_key_file = configuration_protected_settings.get(
                    self.sslKeyPemFile)

                if fe_ssl_cert_file and fe_ssl_key_file:
                    self.__set_inference_ssl_from_file(
                        configuration_protected_settings, fe_ssl_cert_file,
                        fe_ssl_key_file)

        return PatchExtension(
            auto_upgrade_minor_version=auto_upgrade_minor_version,
            release_train=release_train,
            version=version,
            configuration_settings=configuration_settings,
            configuration_protected_settings=configuration_protected_settings)
示例#8
0
 def test_service_response_error(self):
     azure_error = ServiceResponseError("test_error_msg")
     cli_error = helpers.map_azure_error_to_cli_error(azure_error)
     mock_error = AzureResponseError("test_error_msg")
     self.check_error_equality(cli_error, mock_error)
示例#9
0
def output(cmd,
           job_id,
           resource_group_name=None,
           workspace_name=None,
           location=None):
    """
    Get the results of running a Q# job.
    """
    import tempfile
    import json
    import os
    from azure.cli.command_modules.storage._client_factory import blob_data_service_factory

    path = os.path.join(tempfile.gettempdir(), job_id)
    info = WorkspaceInfo(cmd, resource_group_name, workspace_name, location)
    client = cf_jobs(cmd.cli_ctx, info.subscription, info.resource_group,
                     info.name, info.location)
    job = client.get(job_id)

    if os.path.exists(path):
        logger.debug("Using existing blob from %s", path)
    else:
        logger.debug("Downloading job results blob into %s", path)

        if job.status != "Succeeded":
            return f"Job status: {job.status}. Output only available if Succeeded."

        args = _parse_blob_url(job.output_data_uri)
        blob_service = blob_data_service_factory(cmd.cli_ctx, args)
        blob_service.get_blob_to_path(args['container'], args['blob'], path)

    with open(path) as json_file:
        lines = [line.strip() for line in json_file.readlines()]

        # Receiving an empty response is valid.
        if len(lines) == 0:
            return

        if job.target.startswith("microsoft.simulator"):
            result_start_line = len(lines) - 1
            is_result_string = lines[-1].endswith('"')
            if is_result_string:
                while result_start_line >= 0 and not lines[
                        result_start_line].startswith('"'):
                    result_start_line -= 1
            if result_start_line < 0:
                raise AzureResponseError(
                    "Job output is malformed, mismatched quote characters.")

            # Print the job output and then the result of the operation as a histogram.
            # If the result is a string, trim the quotation marks.
            print('\n'.join(lines[:result_start_line]))
            raw_result = ' '.join(lines[result_start_line:])
            result = raw_result[1:-1] if is_result_string else raw_result
            print('_' * len(result) + '\n')

            json_string = '{ "histogram" : { "' + result + '" : 1 } }'
            data = json.loads(json_string)
        else:
            json_file.seek(0)  # Reset the file pointer before loading
            data = json.load(json_file)
        return data
示例#10
0
def connection_create(
        cmd,
        client,  # pylint: disable=too-many-locals
        connection_name=None,
        client_type=None,
        source_resource_group=None,
        source_id=None,
        target_resource_group=None,
        target_id=None,
        secret_auth_info=None,
        secret_auth_info_auto=None,
        user_identity_auth_info=None,
        system_identity_auth_info=None,
        service_principal_auth_info_secret=None,
        key_vault_id=None,
        service_endpoint=None,
        new_addon=False,
        no_wait=False,
        cluster=None,
        scope=None,
        enable_csi=False,  # Resource.KubernetesCluster
        site=None,  # Resource.WebApp
        spring=None,
        app=None,
        deployment='default',  # Resource.SpringCloud
        server=None,
        database=None,  # Resource.*Postgres, Resource.*Sql*
        vault=None,  # Resource.KeyVault
        account=None,  # Resource.Storage*
        key_space=None,
        graph=None,
        table=None,  # Resource.Cosmos*,
        config_store=None,  # Resource.AppConfig
        namespace=None,  # Resource.EventHub
        webpubsub=None,  # Resource.WebPubSub
        signalr=None):  # Resource.SignalR

    if not source_id:
        raise RequiredArgumentMissingError(err_msg.format('--source-id'))
    if not new_addon and not target_id:
        raise RequiredArgumentMissingError(err_msg.format('--target-id'))

    all_auth_info = []
    if secret_auth_info is not None:
        all_auth_info.append(secret_auth_info)
    if secret_auth_info_auto is not None:
        all_auth_info.append(secret_auth_info_auto)
    if user_identity_auth_info is not None:
        all_auth_info.append(user_identity_auth_info)
    if system_identity_auth_info is not None:
        all_auth_info.append(system_identity_auth_info)
    if service_principal_auth_info_secret is not None:
        all_auth_info.append(service_principal_auth_info_secret)
    if not new_addon and len(all_auth_info) != 1:
        raise ValidationError('Only one auth info is needed')
    auth_info = all_auth_info[0] if len(all_auth_info) == 1 else None

    parameters = {
        'target_service': {
            "type": "AzureResource",
            "id": target_id
        },
        'auth_info': auth_info,
        'secret_store': {
            'key_vault_id': key_vault_id,
        },
        'client_type': client_type,
        'scope': scope
    }

    # HACK: set user token to work around OBO
    source_type = get_source_resource_name(cmd)
    target_type = get_target_resource_name(cmd)
    client = set_user_token_by_source_and_target(client, cmd.cli_ctx,
                                                 source_type, target_type)

    if key_vault_id:
        client = set_user_token_header(client, cmd.cli_ctx)
        from ._utils import create_key_vault_reference_connection_if_not_exist
        create_key_vault_reference_connection_if_not_exist(
            cmd, client, source_id, key_vault_id)
    elif auth_info['auth_type'] == 'secret' and 'secret_info' in auth_info \
            and auth_info['secret_info']['secret_type'] == 'keyVaultSecretReference':
        raise ValidationError('--vault-id must be provided to use secret-name')

    if service_endpoint:
        client = set_user_token_header(client, cmd.cli_ctx)
        parameters['v_net_solution'] = {'type': 'serviceEndpoint'}

    if enable_csi:
        parameters['target_service']['resource_properties'] = {
            'type': 'KeyVault',
            'connect_as_kubernetes_csi_driver': enable_csi,
        }

    if new_addon:
        addon = AddonFactory.get(target_type)(cmd, source_id)
        target_id, auth_info = addon.provision()
        parameters['target_service'] = {
            "type": "AzureResource",
            "id": target_id
        }
        parameters['auth_info'] = auth_info
        logger.warning('Start creating the connection')

        try:
            linker = client.begin_create_or_update(resource_uri=source_id,
                                                   linker_name=connection_name,
                                                   parameters=parameters)
            return linker
        except Exception as e:
            logger.warning('Connection creation failed, start rolling back')
            addon.rollback()
            raise AzureResponseError(
                '{}. Provision failed, please create the target resource '
                'manually and then create the connection.'.format(str(e)))

    validate_service_state(parameters)
    return auto_register(sdk_no_wait,
                         no_wait,
                         client.begin_create_or_update,
                         resource_uri=source_id,
                         linker_name=connection_name,
                         parameters=parameters)
示例#11
0
def connection_create(
        cmd,
        client,  # pylint: disable=too-many-locals
        connection_name=None,
        client_type=None,
        source_resource_group=None,
        source_id=None,
        target_resource_group=None,
        target_id=None,
        secret_auth_info=None,
        secret_auth_info_auto=None,
        user_identity_auth_info=None,
        system_identity_auth_info=None,
        service_principal_auth_info_secret=None,
        key_vault_id=None,
        new_addon=False,
        no_wait=False,
        site=None,  # Resource.WebApp
        spring=None,
        app=None,
        deployment=None,  # Resource.SpringCloud
        server=None,
        database=None,  # Resource.*Postgres, Resource.*Sql*
        vault=None,  # Resource.KeyVault
        account=None,  # Resource.Storage*
        key_space=None,
        graph=None,
        table=None,  # Resource.Cosmos*,
        config_store=None,  # Resource.AppConfig
        namespace=None,  # Resource.EventHub
        signalr=None):  # Resource.SignalR

    if not source_id:
        raise RequiredArgumentMissingError(err_msg.format('--source-id'))
    if not new_addon and not target_id:
        raise RequiredArgumentMissingError(err_msg.format('--target-id'))

    all_auth_info = []
    if secret_auth_info is not None:
        all_auth_info.append(secret_auth_info)
    if secret_auth_info_auto is not None:
        all_auth_info.append(secret_auth_info_auto)
    if user_identity_auth_info is not None:
        all_auth_info.append(user_identity_auth_info)
    if system_identity_auth_info is not None:
        all_auth_info.append(system_identity_auth_info)
    if service_principal_auth_info_secret is not None:
        all_auth_info.append(service_principal_auth_info_secret)
    if not new_addon and len(all_auth_info) != 1:
        raise ValidationError('Only one auth info is needed')
    auth_info = all_auth_info[0] if len(all_auth_info) == 1 else None

    parameters = {
        'target_id': target_id,
        'auth_info': auth_info,
        'secret_store': {
            'key_vault_id': key_vault_id,
        },
        'client_type': client_type
    }

    # HACK: set user token to work around OBO
    target_type = get_target_resource_name(cmd)
    if target_type in TARGET_RESOURCES_USERTOKEN:
        client = set_user_token_header(client, cmd.cli_ctx)

    if key_vault_id:
        client = set_user_token_header(client, cmd.cli_ctx)
        from ._utils import create_key_vault_reference_connection_if_not_exist
        create_key_vault_reference_connection_if_not_exist(
            cmd, client, source_id, key_vault_id)

    if new_addon:
        addon = AddonFactory.get(target_type)(cmd, source_id)
        target_id, auth_info = addon.provision()
        parameters['target_id'] = target_id
        parameters['auth_info'] = auth_info
        logger.warning('Start creating the connection')

        try:
            linker = client.begin_create_or_update(resource_uri=source_id,
                                                   linker_name=connection_name,
                                                   parameters=parameters)
            return linker
        except Exception as e:
            logger.warning('Connection creation failed, start rolling back')
            addon.rollback()
            raise AzureResponseError(
                '{}. Provision failed, please create the target resource '
                'manually and then create the connection.'.format(str(e)))

    validate_service_state(parameters)
    return auto_register(sdk_no_wait,
                         no_wait,
                         client.begin_create_or_update,
                         resource_uri=source_id,
                         linker_name=connection_name,
                         parameters=parameters)
    def Update(self, cmd, resource_group_name, cluster_name,
               auto_upgrade_minor_version, release_train, version,
               configuration_settings, configuration_protected_settings):
        self.__normalize_config(configuration_settings,
                                configuration_protected_settings)

        if len(configuration_protected_settings) > 0:
            subscription_id = get_subscription_id(cmd.cli_ctx)

            if self.AZURE_LOG_ANALYTICS_CONNECTION_STRING not in configuration_protected_settings:
                try:
                    _, shared_key = _get_log_analytics_ws_connection_string(
                        cmd, subscription_id, resource_group_name,
                        cluster_name, '', True)
                    configuration_protected_settings[
                        self.
                        AZURE_LOG_ANALYTICS_CONNECTION_STRING] = shared_key
                    logger.info(
                        "Get log analytics connection string succeeded.")
                except azure.core.exceptions.HttpResponseError:
                    logger.info(
                        "Failed to get log analytics connection string.")

            if self.RELAY_SERVER_CONNECTION_STRING not in configuration_protected_settings:
                try:
                    relay_connection_string, _, _ = _get_relay_connection_str(
                        cmd, subscription_id, resource_group_name,
                        cluster_name, '', self.RELAY_HC_AUTH_NAME, True)
                    configuration_protected_settings[
                        self.
                        RELAY_SERVER_CONNECTION_STRING] = relay_connection_string
                    logger.info("Get relay connection string succeeded.")
                except azure.mgmt.relay.models.ErrorResponseException as ex:
                    if ex.response.status_code == 404:
                        raise ResourceNotFoundError(
                            "Relay server not found.") from ex
                    raise AzureResponseError(
                        "Failed to get relay connection string.") from ex

            if self.SERVICE_BUS_CONNECTION_STRING not in configuration_protected_settings:
                try:
                    service_bus_connection_string, _ = _get_service_bus_connection_string(
                        cmd, subscription_id, resource_group_name,
                        cluster_name, '', {}, True)
                    configuration_protected_settings[
                        self.
                        SERVICE_BUS_CONNECTION_STRING] = service_bus_connection_string
                    logger.info("Get service bus connection string succeeded.")
                except azure.core.exceptions.HttpResponseError as ex:
                    if ex.response.status_code == 404:
                        raise ResourceNotFoundError(
                            "Service bus not found.") from ex
                    raise AzureResponseError(
                        "Failed to get service bus connection string.") from ex

            configuration_protected_settings = _dereference(
                self.reference_mapping, configuration_protected_settings)

            if self.sslKeyPemFile in configuration_protected_settings and \
                    self.sslCertPemFile in configuration_protected_settings:
                logger.info(
                    f"Both {self.sslKeyPemFile} and {self.sslCertPemFile} are set, update ssl key."
                )
                self.__set_inference_ssl_from_file(
                    configuration_protected_settings)

        return PatchExtension(
            auto_upgrade_minor_version=auto_upgrade_minor_version,
            release_train=release_train,
            version=version,
            configuration_settings=configuration_settings,
            configuration_protected_settings=configuration_protected_settings)