Skip to content

Commit

Permalink
[Cognitive Services] Support ApiProperties which enable creating QnAM…
Browse files Browse the repository at this point in the history
…aker (Azure#7034)
  • Loading branch information
yangyuan authored and troydai committed Aug 17, 2018
1 parent ebfb323 commit c39f733
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 3 deletions.
1 change: 1 addition & 0 deletions azure-cli2017.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@
<Compile Include="command_modules\azure-cli-cloud\setup.py" />
<Compile Include="command_modules\azure-cli-cognitiveservices\azure\cli\command_modules\cognitiveservices\commands.py" />
<Compile Include="command_modules\azure-cli-cognitiveservices\azure\cli\command_modules\cognitiveservices\custom.py" />
<Compile Include="command_modules\azure-cli-cognitiveservices\azure\cli\command_modules\cognitiveservices\tests\latest\test_api_properties.py" />
<Compile Include="command_modules\azure-cli-cognitiveservices\azure\cli\command_modules\cognitiveservices\tests\latest\test_cognitiveservices_command.py" />
<Compile Include="command_modules\azure-cli-cognitiveservices\azure\cli\command_modules\cognitiveservices\_client_factory.py" />
<Compile Include="command_modules\azure-cli-cognitiveservices\azure\cli\command_modules\cognitiveservices\_help.py" />
Expand Down
4 changes: 4 additions & 0 deletions src/command_modules/azure-cli-cognitiveservices/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Release History
===============

0.2.1
+++++
* Add new parameter --api-properties, which is required for creating some of the services.

0.2.0
+++++
* BREAKING CHANGE: 'show' commands log error message and fail with exit code of 3 upon a missing resource.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,72 @@
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import re
from knack.arguments import CLIArgumentType
from knack.log import get_logger

from azure.cli.core.commands.parameters import (
tags_type,
resource_group_name_type,
get_resource_name_completion_list)
from azure.cli.core.util import (shell_safe_json_parse, CLIError)

from azure.cli.core.commands.validators import validate_tag

logger = get_logger(__name__)
name_arg_type = CLIArgumentType(options_list=['--name', '-n'], metavar='NAME')


def extract_key_values_pairs(api_properties):
api_properties_dict = {}
for item in api_properties:
api_properties_dict.update(validate_tag(item))
return api_properties_dict


def validate_api_properties(ns):
""" Extracts JSON format or 'a=b c=d' format as api properties """
api_properties = ns.api_properties

if api_properties is None:
return

if len(api_properties) > 1:
ns.api_properties = extract_key_values_pairs(api_properties)
else:
string = api_properties[0]
try:
ns.api_properties = shell_safe_json_parse(string)
return
except CLIError:
result = extract_key_values_pairs([string])
if _is_suspected_json(string):
logger.warning('Api properties looks like a JSON format but not valid, interpreted as key=value pairs:'
' %s', str(result))
ns.api_properties = result
return


def _is_suspected_json(string):
""" If the string looks like a JSON """
if string.startswith('{') or string.startswith('\'{') or string.startswith('\"{'):
return True
if string.startswith('[') or string.startswith('\'[') or string.startswith('\"['):
return True
if re.match(r"^['\"\s]*{.+}|\[.+\]['\"\s]*$", string):
return True

return False


api_properties_type = CLIArgumentType(
validator=validate_api_properties,
help="Api properties in JSON format or a=b c=d format. Some cognitive services (i.e. QnA Maker) "
"require extra api properties to create the account.",
nargs='*'
)


def load_arguments(self, _):
with self.argument_context('cognitiveservices') as c:
c.argument('account_name', arg_type=name_arg_type, help='cognitive service account name',
Expand All @@ -23,6 +78,7 @@ def load_arguments(self, _):
c.argument('kind', help='the API name of cognitive services account')
c.argument('tags', tags_type)
c.argument('key_name', required=True, help='Key name to generate', choices=['key1', 'key2'])
c.argument('api_properties', api_properties_type)

with self.argument_context('cognitiveservices account create') as c:
c.argument('yes', action='store_true', help='Do not prompt for terms confirmation')
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def list_resources(client, resource_group_name=None):


def create(
client, resource_group_name, account_name, sku_name, kind, location, tags=None, yes=None):
client, resource_group_name, account_name, sku_name, kind, location, tags=None, api_properties=None, yes=None):

terms = 'Notice\nMicrosoft will use data you send to Bing Search Services'\
' or the Translator Speech API to improve Microsoft products and services.'\
Expand All @@ -43,7 +43,11 @@ def create(
if not option:
raise CLIError('Operation cancelled.')
sku = Sku(sku_name)
properties = {}

if api_properties is None:
properties = {}
else:
properties = {"apiProperties": api_properties}
params = CognitiveServicesAccountCreateParameters(sku, kind, location, properties, tags)
return client.create(resource_group_name, account_name, params)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
interactions:
- request:
body: '{"location": "westus", "tags": {"product": "azurecli", "cause": "automation",
"date": "2018-08-13T20:59:32Z"}}'
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
CommandName: [group create]
Connection: [keep-alive]
Content-Length: ['110']
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.6.5 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.1
msrest_azure/0.4.34 resourcemanagementclient/2.0.0 Azure-SDK-For-Python
AZURECLI/2.0.44]
accept-language: [en-US]
method: PUT
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001?api-version=2018-05-01
response:
body: {string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001","name":"clitest.rg000001","location":"westus","tags":{"product":"azurecli","cause":"automation","date":"2018-08-13T20:59:32Z"},"properties":{"provisioningState":"Succeeded"}}'}
headers:
cache-control: [no-cache]
content-length: ['384']
content-type: [application/json; charset=utf-8]
date: ['Mon, 13 Aug 2018 20:59:34 GMT']
expires: ['-1']
pragma: [no-cache]
strict-transport-security: [max-age=31536000; includeSubDomains]
x-content-type-options: [nosniff]
x-ms-ratelimit-remaining-subscription-writes: ['1199']
status: {code: 201, message: Created}
- request:
body: '{"sku": {"name": "S0"}, "kind": "QnAMaker", "location": "westus", "properties":
{"apiProperties": {"qnaRuntimeEndpoint": "https://cs-cli-test-qnamaker.azurewebsites.net"}}}'
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
CommandName: [cognitiveservices account create]
Connection: [keep-alive]
Content-Length: ['172']
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.6.5 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.1
msrest_azure/0.4.34 cognitiveservicesmanagementclient/1.0.0 Azure-SDK-For-Python
AZURECLI/2.0.44]
accept-language: [en-US]
method: PUT
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.CognitiveServices/accounts/cs_cli_test_000002?api-version=2017-04-18
response:
body: {string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.CognitiveServices/accounts/cs_cli_test_000002","name":"cs_cli_test_000002","type":"Microsoft.CognitiveServices/accounts","etag":"\"6900ddcd-0000-0000-0000-5b71f1370000\"","location":"westus","sku":{"name":"S0"},"kind":"QnAMaker","properties":{"endpoint":"https://westus.api.cognitive.microsoft.com/qnamaker/v4.0","internalId":"5b7a3f0503a14481bffdd72294e77ff1","dateCreated":"2018-08-13T20:59:35.8473162Z","apiProperties":{"qnaRuntimeEndpoint":"https://cs-cli-test-qnamaker.azurewebsites.net"},"provisioningState":"Succeeded"}}'}
headers:
cache-control: [no-cache]
content-length: ['693']
content-type: [application/json; charset=utf-8]
date: ['Mon, 13 Aug 2018 20:59:35 GMT']
etag: ['"6900ddcd-0000-0000-0000-5b71f1370000"']
expires: ['-1']
pragma: [no-cache]
server: [Microsoft-IIS/10.0]
strict-transport-security: [max-age=31536000; includeSubDomains]
x-aspnet-version: [4.0.30319]
x-content-type-options: [nosniff]
x-ms-ratelimit-remaining-subscription-writes: ['1199']
x-powered-by: [ASP.NET]
status: {code: 201, message: Created}
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
CommandName: [cognitiveservices account delete]
Connection: [keep-alive]
Content-Length: ['0']
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.6.5 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.1
msrest_azure/0.4.34 cognitiveservicesmanagementclient/1.0.0 Azure-SDK-For-Python
AZURECLI/2.0.44]
accept-language: [en-US]
method: DELETE
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.CognitiveServices/accounts/cs_cli_test_000002?api-version=2017-04-18
response:
body: {string: ''}
headers:
cache-control: [no-cache]
content-length: ['0']
date: ['Mon, 13 Aug 2018 20:59:37 GMT']
expires: ['-1']
pragma: [no-cache]
server: [Microsoft-IIS/10.0]
strict-transport-security: [max-age=31536000; includeSubDomains]
x-aspnet-version: [4.0.30319]
x-content-type-options: [nosniff]
x-ms-ratelimit-remaining-subscription-deletes: ['14999']
x-powered-by: [ASP.NET]
status: {code: 200, message: OK}
- request:
body: '{"sku": {"name": "S0"}, "kind": "QnAMaker", "location": "westus", "properties":
{"apiProperties": {"qnaRuntimeEndpoint": "https://cs-cli-test-qnamaker.azurewebsites.net"}}}'
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
CommandName: [cognitiveservices account create]
Connection: [keep-alive]
Content-Length: ['172']
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.6.5 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.1
msrest_azure/0.4.34 cognitiveservicesmanagementclient/1.0.0 Azure-SDK-For-Python
AZURECLI/2.0.44]
accept-language: [en-US]
method: PUT
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.CognitiveServices/accounts/cs_cli_test_000002?api-version=2017-04-18
response:
body: {string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.CognitiveServices/accounts/cs_cli_test_000002","name":"cs_cli_test_000002","type":"Microsoft.CognitiveServices/accounts","etag":"\"6900e1cd-0000-0000-0000-5b71f13a0000\"","location":"westus","sku":{"name":"S0"},"kind":"QnAMaker","properties":{"endpoint":"https://westus.api.cognitive.microsoft.com/qnamaker/v4.0","internalId":"8c302dd2c300473297d139048b8ed560","dateCreated":"2018-08-13T20:59:38.1208213Z","apiProperties":{"qnaRuntimeEndpoint":"https://cs-cli-test-qnamaker.azurewebsites.net"},"provisioningState":"Succeeded"}}'}
headers:
cache-control: [no-cache]
content-length: ['693']
content-type: [application/json; charset=utf-8]
date: ['Mon, 13 Aug 2018 20:59:37 GMT']
etag: ['"6900e1cd-0000-0000-0000-5b71f13a0000"']
expires: ['-1']
pragma: [no-cache]
server: [Microsoft-IIS/10.0]
strict-transport-security: [max-age=31536000; includeSubDomains]
x-aspnet-version: [4.0.30319]
x-content-type-options: [nosniff]
x-ms-ratelimit-remaining-subscription-writes: ['1199']
x-powered-by: [ASP.NET]
status: {code: 201, message: Created}
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
CommandName: [cognitiveservices account delete]
Connection: [keep-alive]
Content-Length: ['0']
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.6.5 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.1
msrest_azure/0.4.34 cognitiveservicesmanagementclient/1.0.0 Azure-SDK-For-Python
AZURECLI/2.0.44]
accept-language: [en-US]
method: DELETE
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest.rg000001/providers/Microsoft.CognitiveServices/accounts/cs_cli_test_000002?api-version=2017-04-18
response:
body: {string: ''}
headers:
cache-control: [no-cache]
content-length: ['0']
date: ['Mon, 13 Aug 2018 20:59:38 GMT']
expires: ['-1']
pragma: [no-cache]
server: [Microsoft-IIS/10.0]
strict-transport-security: [max-age=31536000; includeSubDomains]
x-aspnet-version: [4.0.30319]
x-content-type-options: [nosniff]
x-ms-ratelimit-remaining-subscription-deletes: ['14999']
x-powered-by: [ASP.NET]
status: {code: 200, message: OK}
- request:
body: null
headers:
Accept: [application/json]
Accept-Encoding: ['gzip, deflate']
CommandName: [group delete]
Connection: [keep-alive]
Content-Length: ['0']
Content-Type: [application/json; charset=utf-8]
User-Agent: [python/3.6.5 (Windows-10-10.0.17134-SP0) requests/2.19.1 msrest/0.5.1
msrest_azure/0.4.34 resourcemanagementclient/2.0.0 Azure-SDK-For-Python
AZURECLI/2.0.44]
accept-language: [en-US]
method: DELETE
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest.rg000001?api-version=2018-05-01
response:
body: {string: ''}
headers:
cache-control: [no-cache]
content-length: ['0']
date: ['Mon, 13 Aug 2018 20:59:39 GMT']
expires: ['-1']
location: ['https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1DTElURVNUOjJFUkdLWUtQN1E3M1pBVzVRQ0lYUjZZNFpBQ1haUVNGQVJMT1RVMnwwQjQxMUJEQUMwOEY4OEZELVdFU1RVUyIsImpvYkxvY2F0aW9uIjoid2VzdHVzIn0?api-version=2018-05-01']
pragma: [no-cache]
strict-transport-security: [max-age=31536000; includeSubDomains]
x-content-type-options: [nosniff]
x-ms-ratelimit-remaining-subscription-deletes: ['14999']
status: {code: 202, message: Accepted}
version: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import unittest

from azure.cli.testsdk import ScenarioTest, ResourceGroupPreparer


class CognitiveServicesApiPropertiesTests(ScenarioTest):
@ResourceGroupPreparer()
def test_cognitiveservices_create_api_properties(self, resource_group):
sname = self.create_random_name(prefix='cs_cli_test_', length=16)

self.kwargs.update({
'sname': sname,
'kind': 'QnAMaker',
'sku': 'S0',
'location': 'westus',
'apiProperties': 'qnaRuntimeEndpoint=https://cs-cli-test-qnamaker.azurewebsites.net',
'apiPropertiesJson': '{\\\"qnaRuntimeEndpoint\\\":\\\"https://cs-cli-test-qnamaker.azurewebsites.net\\\"}',
})

# test to create cognitive services account
self.cmd('az cognitiveservices account create -n {sname} -g {rg} --kind {kind} --sku {sku} -l {location} '
'--api-properties {apiProperties} --yes',
checks=[self.check('name', '{sname}'),
self.check('location', '{location}'),
self.check('sku.name', '{sku}'),
self.check('provisioningState', 'Succeeded')])

# delete the cognitive services account
ret = self.cmd('az cognitiveservices account delete -n {sname} -g {rg}')
self.assertEqual(ret.exit_code, 0)

# test to create cognitive services account
self.cmd('az cognitiveservices account create -n {sname} -g {rg} --kind {kind} --sku {sku} -l {location} '
'--api-properties {apiPropertiesJson} --yes',
checks=[self.check('name', '{sname}'),
self.check('location', '{location}'),
self.check('sku.name', '{sku}'),
self.check('provisioningState', 'Succeeded')])

# delete the cognitive services account
ret = self.cmd('az cognitiveservices account delete -n {sname} -g {rg}')
self.assertEqual(ret.exit_code, 0)


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion src/command_modules/azure-cli-cognitiveservices/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
logger.warn("Wheel is not available, disabling bdist_wheel hook")
cmdclass = {}

VERSION = "0.2.0"
VERSION = "0.2.1"
# The full list of classifiers is available at
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
CLASSIFIERS = [
Expand Down

0 comments on commit c39f733

Please sign in to comment.