Repository navigation
[Cognitive Services] az cognitiveservices account [project|connection]: Add support for AI Foundry project and connection management
#32336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
kai ru (kairu-ms)
merged 13 commits into
Azure:dev
from
CarlOchs:cogsvc_integrate_ml_commands
Nov 6, 2025
Merged
Changes from 5 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
5a1c2d5
Bump azure-mgmt-cognitiveservices to 14.0.0
CarlOchs 20305b7
Add support for Cog Svc/AI projects and connections
CarlOchs f493401
Fix linter errors. Add correct project update command
CarlOchs 1e1b8ea
Fix linter errors; add local linter exclusions
CarlOchs 7a25448
Fix whitespace issues.
CarlOchs d101fc1
[azdev style] Remove azure.ai module dependency
CarlOchs 3054d12
Update help messages.
CarlOchs b8e84ce
Fix whitespace issue
CarlOchs 6fafe0a
Rerun all cognitiveservices test live to update recordings
CarlOchs 0d25186
Mask secrets
CarlOchs c2c6e42
Add license headers
CarlOchs 5a854bc
Merge branch 'Azure:dev' into cogsvc_integrate_ml_commands
CarlOchs 79b141c
Merge branch 'Azure:dev' into cogsvc_integrate_ml_commands
CarlOchs File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
220 changes: 220 additions & 0 deletions
220
src/azure-cli/azure/cli/command_modules/cognitiveservices/_ml_utils.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,220 @@ | ||
| from azure.cli.core.azclierror import FileOperationError, InvalidArgumentValueError | ||
| from azure.mgmt.cognitiveservices.models import ConnectionCategory | ||
| from os import PathLike | ||
| from typing import IO, Any, AnyStr, Dict, List, Optional, Union | ||
|
|
||
| _ML_CONNECTION_TYPE_TO_COGNITIVE_SERVICES_CONNECTION_TYPE = { | ||
| "PythonFeed": ConnectionCategory.PYTHON_FEED, | ||
| "ContainerRegistry": ConnectionCategory.CONTAINER_REGISTRY, | ||
| "Git": ConnectionCategory.GIT, | ||
| "S3": ConnectionCategory.S3, | ||
| "Snowflake": ConnectionCategory.SNOWFLAKE, | ||
| "AzureSqlDb": ConnectionCategory.AZURE_SQL_DB, | ||
| "AzureSynapseAnalytics": ConnectionCategory.AZURE_SYNAPSE_ANALYTICS, | ||
| "AzureMySqlDb": ConnectionCategory.AZURE_MY_SQL_DB, | ||
| "AzurePostgresDb": ConnectionCategory.AZURE_POSTGRES_DB, | ||
| "ADLSGen2": ConnectionCategory.ADLS_GEN2, | ||
| "Redis": ConnectionCategory.REDIS, | ||
| "ApiKey": ConnectionCategory.API_KEY, | ||
| "AzureOpenAI": ConnectionCategory.AZURE_OPEN_AI, | ||
| "AzureOpenAi": ConnectionCategory.AZURE_OPEN_AI, | ||
| "AIServices": ConnectionCategory.AI_SERVICES, | ||
| "AiServices": ConnectionCategory.AI_SERVICES, | ||
| "CognitiveSearch": ConnectionCategory.COGNITIVE_SEARCH, | ||
| "CognitiveService": ConnectionCategory.COGNITIVE_SERVICE, | ||
| "CustomKeys": ConnectionCategory.CUSTOM_KEYS, | ||
| "AzureBlob": ConnectionCategory.AZURE_BLOB, | ||
| "AzureOneLake": ConnectionCategory.AZURE_ONE_LAKE, | ||
| "CosmosDb": ConnectionCategory.COSMOS_DB, | ||
| "CosmosDbMongoDbApi": ConnectionCategory.COSMOS_DB_MONGO_DB_API, | ||
| "AzureDataExplorer": ConnectionCategory.AZURE_DATA_EXPLORER, | ||
| "AzureMariaDb": ConnectionCategory.AZURE_MARIA_DB, | ||
| "AzureDatabricksDeltaLake": ConnectionCategory.AZURE_DATABRICKS_DELTA_LAKE, | ||
| "AzureSqlMi": ConnectionCategory.AZURE_SQL_MI, | ||
| "AzureTableStorage": ConnectionCategory.AZURE_TABLE_STORAGE, | ||
| "AmazonRdsForOracle": ConnectionCategory.AMAZON_RDS_FOR_ORACLE, | ||
| "AmazonRdsForSqlServer": ConnectionCategory.AMAZON_RDS_FOR_SQL_SERVER, | ||
| "AmazonRedshift": ConnectionCategory.AMAZON_REDSHIFT, | ||
| "Db2": ConnectionCategory.DB2, | ||
| "Drill": ConnectionCategory.DRILL, | ||
| "GoogleBigQuery": ConnectionCategory.GOOGLE_BIG_QUERY, | ||
| "Greenplum": ConnectionCategory.GREENPLUM, | ||
| "Hbase": ConnectionCategory.HBASE, | ||
| "Hive": ConnectionCategory.HIVE, | ||
| "Impala": ConnectionCategory.IMPALA, | ||
| "Informix": ConnectionCategory.INFORMIX, | ||
| "MariaDb": ConnectionCategory.MARIA_DB, | ||
| "MicrosoftAccess": ConnectionCategory.MICROSOFT_ACCESS, | ||
| "MySql": ConnectionCategory.MY_SQL, | ||
| "Netezza": ConnectionCategory.NETEZZA, | ||
| "Oracle": ConnectionCategory.ORACLE, | ||
| "Phoenix": ConnectionCategory.PHOENIX, | ||
| "PostgreSql": ConnectionCategory.POSTGRE_SQL, | ||
| "Presto": ConnectionCategory.PRESTO, | ||
| "SapOpenHub": ConnectionCategory.SAP_OPEN_HUB, | ||
| "SapBw": ConnectionCategory.SAP_BW, | ||
| "SapHana": ConnectionCategory.SAP_HANA, | ||
| "SapTable": ConnectionCategory.SAP_TABLE, | ||
| "Spark": ConnectionCategory.SPARK, | ||
| "SqlServer": ConnectionCategory.SQL_SERVER, | ||
| "Sybase": ConnectionCategory.SYBASE, | ||
| "Teradata": ConnectionCategory.TERADATA, | ||
| "Vertica": ConnectionCategory.VERTICA, | ||
| "Pinecone": ConnectionCategory.PINECONE, | ||
| "Cassandra": ConnectionCategory.CASSANDRA, | ||
| "Couchbase": ConnectionCategory.COUCHBASE, | ||
| "MongoDbV2": ConnectionCategory.MONGO_DB_V2, | ||
| "MongoDbAtlas": ConnectionCategory.MONGO_DB_ATLAS, | ||
| "AmazonS3Compatible": ConnectionCategory.AMAZON_S3_COMPATIBLE, | ||
| "FileServer": ConnectionCategory.FILE_SERVER, | ||
| "FtpServer": ConnectionCategory.FTP_SERVER, | ||
| "GoogleCloudStorage": ConnectionCategory.GOOGLE_CLOUD_STORAGE, | ||
| "Hdfs": ConnectionCategory.HDFS, | ||
| "OracleCloudStorage": ConnectionCategory.ORACLE_CLOUD_STORAGE, | ||
| "Sftp": ConnectionCategory.SFTP, | ||
| "GenericHttp": ConnectionCategory.GENERIC_HTTP, | ||
| "ODataRest": ConnectionCategory.O_DATA_REST, | ||
| "Odbc": ConnectionCategory.ODBC, | ||
| "GenericRest": ConnectionCategory.GENERIC_REST, | ||
| "AmazonMws": ConnectionCategory.AMAZON_MWS, | ||
| "Concur": ConnectionCategory.CONCUR, | ||
| "Dynamics": ConnectionCategory.DYNAMICS, | ||
| "DynamicsAx": ConnectionCategory.DYNAMICS_AX, | ||
| "DynamicsCrm": ConnectionCategory.DYNAMICS_CRM, | ||
| "GoogleAdWords": ConnectionCategory.GOOGLE_AD_WORDS, | ||
| "Hubspot": ConnectionCategory.HUBSPOT, | ||
| "Jira": ConnectionCategory.JIRA, | ||
| "Magento": ConnectionCategory.MAGENTO, | ||
| "Marketo": ConnectionCategory.MARKETO, | ||
| "Office365": ConnectionCategory.OFFICE365, | ||
| "Eloqua": ConnectionCategory.ELOQUA, | ||
| "Responsys": ConnectionCategory.RESPONSYS, | ||
| "OracleServiceCloud": ConnectionCategory.ORACLE_SERVICE_CLOUD, | ||
| "PayPal": ConnectionCategory.PAY_PAL, | ||
| "QuickBooks": ConnectionCategory.QUICK_BOOKS, | ||
| "Salesforce": ConnectionCategory.SALESFORCE, | ||
| "SalesforceServiceCloud": ConnectionCategory.SALESFORCE_SERVICE_CLOUD, | ||
| "SalesforceMarketingCloud": ConnectionCategory.SALESFORCE_MARKETING_CLOUD, | ||
| "SapCloudForCustomer": ConnectionCategory.SAP_CLOUD_FOR_CUSTOMER, | ||
| "SapEcc": ConnectionCategory.SAP_ECC, | ||
| "ServiceNow": ConnectionCategory.SERVICE_NOW, | ||
| "SharePointOnlineList": ConnectionCategory.SHARE_POINT_ONLINE_LIST, | ||
| "Shopify": ConnectionCategory.SHOPIFY, | ||
| "Square": ConnectionCategory.SQUARE, | ||
| "WebTable": ConnectionCategory.WEB_TABLE, | ||
| "Xero": ConnectionCategory.XERO, | ||
| "Zoho": ConnectionCategory.ZOHO, | ||
| "GenericContainerRegistry": ConnectionCategory.GENERIC_CONTAINER_REGISTRY, | ||
| "Elasticsearch": ConnectionCategory.ELASTICSEARCH, | ||
| "OpenAI": ConnectionCategory.OPEN_AI, | ||
| "OpenAi": ConnectionCategory.OPEN_AI, | ||
| "Serp": ConnectionCategory.SERP, | ||
| "BingLLMSearch": ConnectionCategory.BING_LLM_SEARCH, | ||
| "Serverless": ConnectionCategory.SERVERLESS, | ||
| "ManagedOnlineEndpoint": ConnectionCategory.MANAGED_ONLINE_ENDPOINT, | ||
| # The following are from azure.ai.ml.constants._common.ConnectionTypes | ||
| "Custom": ConnectionCategory.CUSTOM_KEYS, | ||
| "AzureDataLakeGen2": ConnectionCategory.ADLS_GEN2, | ||
| "AzureContentSafety": ConnectionCategory.COGNITIVE_SERVICE, | ||
| "AzureSpeechServices": ConnectionCategory.COGNITIVE_SERVICE, | ||
| "AzureAiSearch": ConnectionCategory.COGNITIVE_SEARCH, | ||
| "AzureAiServices": ConnectionCategory.AI_SERVICES, | ||
| } | ||
|
|
||
|
|
||
| def get_valid_mlconn_types(): | ||
| return list(_ML_CONNECTION_TYPE_TO_COGNITIVE_SERVICES_CONNECTION_TYPE.keys()) | ||
|
|
||
|
|
||
| def get_mapped_mlconn_type(ml_connection_type: str): | ||
| from azure.ai.ml._utils.utils import _snake_to_camel as snake_to_camel | ||
| normalized_name = snake_to_camel(ml_connection_type) | ||
| return _ML_CONNECTION_TYPE_TO_COGNITIVE_SERVICES_CONNECTION_TYPE.get(normalized_name) | ||
|
|
||
|
|
||
| def from_ml_connection(mlconn): | ||
| from azure.mgmt.cognitiveservices import models | ||
| import azure.ai.ml.entities as ml_entities | ||
| conn = None | ||
| connection_category = get_mapped_mlconn_type(mlconn.type) | ||
| if connection_category is None: | ||
| raise InvalidArgumentValueError( | ||
| f"Invalid connection type '{mlconn.type}'. ", | ||
| recommendation=[ | ||
| "Verify that the connection type property is set to one of the following values:", | ||
| ', '.join(get_valid_mlconn_types())]) | ||
| match type(mlconn.credentials): | ||
| case ml_entities.PatTokenConfiguration: | ||
| conn = models.PATAuthTypeConnectionProperties( | ||
| credentials=models.ConnectionPersonalAccessToken(pat=mlconn.credentials.pat)) | ||
| case ml_entities.SasTokenConfiguration: | ||
| conn = models.SASAuthTypeConnectionProperties( | ||
| credentials=models.ConnectionSharedAccessSignature(sas=mlconn.credentials.sas_token)) | ||
| case ml_entities.UsernamePasswordConfiguration: | ||
| conn = models.UsernamePasswordAuthTypeConnectionProperties( | ||
| credentials=models.ConnectionUsernamePassword( | ||
| username=mlconn.credentials.username, | ||
| password=mlconn.credentials.password)) | ||
| case ml_entities.ManagedIdentityConfiguration: | ||
| conn = models.ManagedIdentityAuthTypeConnectionProperties( | ||
| credentials=models.ConnectionManagedIdentity( | ||
| client_id=mlconn.credentials.client_id, | ||
| resource_id=mlconn.credentials.resource_id, | ||
| )) | ||
| case ml_entities.ServicePrincipalConfiguration: | ||
| conn = models.ServicePrincipalAuthTypeConnectionProperties( | ||
| credentials=models.ConnectionServicePrincipal( | ||
| client_id=mlconn.credentials.client_id, | ||
| client_secret=mlconn.credentials.client_secret, | ||
| tenant_id=mlconn.credentials.tenant_id | ||
| )) | ||
| case ml_entities.AccessKeyConfiguration: | ||
| conn = models.AccessKeyAuthTypeConnectionProperties( | ||
| credentials=models.ConnectionAccessKey( | ||
| access_key_id=mlconn.credentials.access_key_id, | ||
| secret_access_key=mlconn.credentials.secret_access_key | ||
| ) | ||
| ) | ||
| case ml_entities.ApiKeyConfiguration: | ||
| conn = models.ApiKeyAuthConnectionProperties( | ||
| credentials=models.ConnectionApiKey(key=mlconn.credentials.key) | ||
| ) | ||
| case ml_entities.NoneCredentialConfiguration: | ||
| conn = models.NoneAuthTypeConnectionProperties() | ||
| case ml_entities.AccountKeyConfiguration: | ||
| conn = models.AccountKeyAuthTypeConnectionProperties( | ||
| credentials=models.ConnectionAccountKey( | ||
| key=mlconn.credentials.account_key | ||
| ) | ||
| ) | ||
| case ml_entities.AadCredentialConfiguration: | ||
| conn = models.AADAuthTypeConnectionProperties() | ||
| case _: | ||
| conn = models.AADAuthTypeConnectionProperties() | ||
| conn.category = connection_category | ||
| conn.target = mlconn.target | ||
| conn.metadata = mlconn.metadata | ||
| return conn | ||
|
|
||
|
|
||
| def load_connection_from_file(source: Union[str, PathLike, IO[AnyStr]], | ||
| params_override: Optional[List[Dict[str, Any]]] = None): | ||
| """ | ||
| Load a connection from a JSON file or string. | ||
| """ | ||
| from azure.ai.ml.entities._load_functions import load_connection | ||
| cogsvc_connection = None | ||
| ml_connection = None | ||
| try: | ||
| ml_connection = load_connection( | ||
| source=source, | ||
| params_override=params_override, | ||
| ) | ||
| # The azure.ai.ml._workspace._ai_workspaces.connection.Connection type maps to the | ||
| # azure.mgmt.cognitiveservices.models.ConnectionPropertiesV2 credentialed subclass type. | ||
| # We need to convert it to the latter type before sending it to the API. | ||
| except Exception as e: | ||
| raise FileOperationError(f"Failed to load connection from {source}: {e}", | ||
| recommendation="Check the file path and format.") | ||
| cogsvc_connection = from_ml_connection(ml_connection) | ||
| return cogsvc_connection |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,6 +121,20 @@ def _validate_subnet(cmd, namespace): | |
| child_name_1=subnet) | ||
|
|
||
|
|
||
| def _validate_user_assigned_identity(cmd, namespace): | ||
| from azure.mgmt.core.tools import resource_id, is_valid_resource_id | ||
| from azure.cli.core.commands.client_factory import get_subscription_id | ||
| if namespace.user_assigned_identity: | ||
| identity = namespace.user_assigned_identity | ||
| if not is_valid_resource_id(identity): | ||
| namespace.user_assigned_identity = resource_id( | ||
| subscription=get_subscription_id(cmd.cli_ctx), | ||
| resource_group=namespace.resource_group_name, | ||
| namespace='Microsoft.ManagedIdentity', | ||
| type='userAssignedIdentities', | ||
| name=identity) | ||
|
|
||
|
|
||
| @Completer | ||
| def sku_name_completer(cmd, prefix, namespace, **kwargs): # pylint: disable=unused-argument | ||
| names = {x.name for x in _sku_filter(cmd, namespace)} | ||
|
|
@@ -183,6 +197,9 @@ def load_arguments(self, _): | |
|
|
||
| with self.argument_context('cognitiveservices account deployment') as c: | ||
| c.argument('deployment_name', help='Cognitive Services account deployment name') | ||
| c.argument('spillover_deployment_name', | ||
| options_list=['--spillover-deployment-name', '--spillover-name'], | ||
| help='The name of the standard deployment to use as a spillover when at capacity.') | ||
|
|
||
| with self.argument_context('cognitiveservices account deployment', arg_group='DeploymentModel') as c: | ||
| c.argument('model_name', help='Cognitive Services account deployment model name.') | ||
|
|
@@ -214,3 +231,32 @@ def load_arguments(self, _): | |
| with self.argument_context('cognitiveservices account commitment-plan', arg_group='Next CommitmentPeriod') as c: | ||
| c.argument('next_count', help='Cognitive Services account commitment plan next commitment period count.') | ||
| c.argument('next_tier', help='Cognitive Services account commitment plan next commitment period tier.') | ||
|
|
||
| with self.argument_context('cognitiveservices account project') as c: | ||
| c.argument('project_name', help='Cognitive Services account project name') | ||
| c.argument('location', arg_type=get_location_type(self.cli_ctx), | ||
| completer=location_completer) | ||
| c.argument('description', help='Description of the project.') | ||
| c.argument('display_name', help='Display name of the project.') | ||
|
|
||
| with self.argument_context('cognitiveservices account project', arg_group='Project Identity') as c: | ||
| c.argument("assign_identity", | ||
| options_list=['--include-system-identity', '--assign-identity'], | ||
| help=('Use with --user-assigned-identity to generate and assign a ' | ||
| 'system managed Azure Active Directory Identity for this project.')) | ||
|
Comment on lines
+245
to
+246
|
||
| c.argument('user_assigned_identity', | ||
| help=('User assigned identity resource ID to use for the project. ' | ||
| 'If not specified, a system assigned identity will be used.'), | ||
| validator=_validate_user_assigned_identity) | ||
|
|
||
| with self.argument_context('cognitiveservices account project create') as c: | ||
| c.argument('description', help='Description of the project.') | ||
| c.argument('display_name', help='Display name of the project.') | ||
|
|
||
| with self.argument_context('cognitiveservices account project connection') as c: | ||
| c.argument('connection_name', help='Cognitive Services account connection name') | ||
| c.argument('file', help='Path to the connection file in JSON or YAML format.') | ||
|
|
||
| with self.argument_context('cognitiveservices account connection') as c: | ||
| c.argument('connection_name', help='Cognitive Services account connection name') | ||
| c.argument('file', help='Path to the connection file in JSON or YAML format.') | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.