Skip to content

Commit e0832af

Browse files
authored
{Misc.} Remove aladdin logic due to service will be sunset (#33104)
1 parent 8fbf679 commit e0832af

File tree

8 files changed

+24
-263
lines changed

8 files changed

+24
-263
lines changed

src/azure-cli-core/azure/cli/core/_help.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ def _print_header(self, cli_name, help_file):
129129
def _print_detailed_help(self, cli_name, help_file):
130130
CLIPrintMixin._print_extensions_msg(help_file)
131131
super()._print_detailed_help(cli_name, help_file)
132-
self._print_az_find_message(help_file.command)
133132

134133
@staticmethod
135134
def _get_choices_defaults_sources_str(p):
@@ -154,12 +153,6 @@ def _print_examples(help_file):
154153
_print_indent('{0}'.format(e.command), indent)
155154
print('')
156155

157-
@staticmethod
158-
def _print_az_find_message(command):
159-
indent = 0
160-
message = 'To search AI knowledge base for examples, use: az find "az {}"'.format(command)
161-
_print_indent(message + '\n', indent)
162-
163156
@staticmethod
164157
def _process_value_sources(p):
165158
commands, strings, urls = [], [], []
@@ -401,10 +394,7 @@ def show_cached_help(self, help_data, args=None):
401394

402395
self._print_cached_help_section(groups_items, "Subgroups:", max_line_len)
403396
self._print_cached_help_section(commands_items, "Commands:", max_line_len)
404-
405-
# Use same az find message as non-cached path
406-
print() # Blank line before the message
407-
self._print_az_find_message('')
397+
print()
408398

409399
from azure.cli.core.util import show_updates_available
410400
show_updates_available(new_line_after=True)

src/azure-cli-core/azure/cli/core/azclierror.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ def __init__(self, error_msg, recommendation=None):
3333
self.recommendations = []
3434
self.set_recommendation(recommendation)
3535

36-
# AI recommendations provided by Aladdin service, with tuple form: (recommendation, description)
37-
self.aladdin_recommendations = []
36+
# example recommendations with tuple form: (recommendation, description)
37+
self.example_recommendations = []
3838

3939
# exception trace for the error
4040
self.exception_trace = None
@@ -50,11 +50,11 @@ def set_recommendation(self, recommendation):
5050
elif isinstance(recommendation, list):
5151
self.recommendations.extend(recommendation)
5252

53-
def set_aladdin_recommendation(self, recommendations):
54-
""" Set aladdin recommendations for the error.
53+
def set_example_recommendation(self, recommendations):
54+
""" Set example recommendations for the error.
5555
One item should be a tuple with the form: (recommendation, description)
5656
"""
57-
self.aladdin_recommendations.extend(recommendations)
57+
self.example_recommendations.extend(recommendations)
5858

5959
def set_exception_trace(self, exception_trace):
6060
self.exception_trace = exception_trace
@@ -80,9 +80,12 @@ def print_error(self):
8080
for recommendation in self.recommendations:
8181
print(recommendation, file=sys.stderr)
8282

83-
if self.aladdin_recommendations:
84-
print('\nExamples from AI knowledge base:', file=sys.stderr)
85-
for recommendation, description in self.aladdin_recommendations:
83+
if self.example_recommendations:
84+
print(file=sys.stderr)
85+
if len(self.example_recommendations) > 1: # contains help examples
86+
print("Examples from command's help:", file=sys.stderr)
87+
88+
for recommendation, description in self.example_recommendations:
8689
print_styled_text(recommendation, file=sys.stderr)
8790
print_styled_text(description, file=sys.stderr)
8891

src/azure-cli-core/azure/cli/core/cloud.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323
# Add names of clouds that don't allow telemetry data collection here such as some air-gapped clouds.
2424
CLOUDS_FORBIDDING_TELEMETRY = ['USSec', 'USNat']
2525

26-
# Add names of clouds that don't allow Aladdin requests for command recommendations here
27-
CLOUDS_FORBIDDING_ALADDIN_REQUEST = ['USSec', 'USNat']
28-
2926

3027
class CloudNotRegisteredException(Exception):
3128
def __init__(self, cloud_name):

src/azure-cli-core/azure/cli/core/command_recommender.py

Lines changed: 4 additions & 205 deletions
Original file line numberDiff line numberDiff line change
@@ -3,89 +3,16 @@
33
# Licensed under the MIT License. See License.txt in the project root for license information.
44
# --------------------------------------------------------------------------------------------
55

6-
from enum import Enum
7-
86
from azure.cli.core import telemetry
97
from knack.log import get_logger
108

119

1210
logger = get_logger(__name__)
1311

1412

15-
class AladdinUserFaultType(Enum):
16-
"""Define the userfault types required by aladdin service
17-
to get the command recommendations"""
18-
19-
ExpectedArgument = 'ExpectedArgument'
20-
UnrecognizedArguments = 'UnrecognizedArguments'
21-
ValidationError = 'ValidationError'
22-
UnknownSubcommand = 'UnknownSubcommand'
23-
MissingRequiredParameters = 'MissingRequiredParameters'
24-
MissingRequiredSubcommand = 'MissingRequiredSubcommand'
25-
StorageAccountNotFound = 'StorageAccountNotFound'
26-
Unknown = 'Unknown'
27-
InvalidJMESPathQuery = 'InvalidJMESPathQuery'
28-
InvalidOutputType = 'InvalidOutputType'
29-
InvalidParameterValue = 'InvalidParameterValue'
30-
UnableToParseCommandInput = 'UnableToParseCommandInput'
31-
ResourceGroupNotFound = 'ResourceGroupNotFound'
32-
InvalidDateTimeArgumentValue = 'InvalidDateTimeArgumentValue'
33-
InvalidResourceGroupName = 'InvalidResourceGroupName'
34-
AzureResourceNotFound = 'AzureResourceNotFound'
35-
InvalidAccountName = 'InvalidAccountName'
36-
37-
38-
def get_error_type(error_msg):
39-
"""The the error type of the failed command from the error message.
40-
The error types are only consumed by aladdin service for better recommendations.
41-
"""
42-
43-
error_type = AladdinUserFaultType.Unknown
44-
if not error_msg:
45-
return error_type.value
46-
47-
error_msg = error_msg.lower()
48-
if 'unrecognized' in error_msg:
49-
error_type = AladdinUserFaultType.UnrecognizedArguments
50-
elif 'expected one argument' in error_msg or 'expected at least one argument' in error_msg \
51-
or 'value required' in error_msg:
52-
error_type = AladdinUserFaultType.ExpectedArgument
53-
elif 'misspelled' in error_msg:
54-
error_type = AladdinUserFaultType.UnknownSubcommand
55-
elif 'arguments are required' in error_msg or 'argument required' in error_msg:
56-
error_type = AladdinUserFaultType.MissingRequiredParameters
57-
if '_subcommand' in error_msg:
58-
error_type = AladdinUserFaultType.MissingRequiredSubcommand
59-
elif '_command_package' in error_msg:
60-
error_type = AladdinUserFaultType.UnableToParseCommandInput
61-
elif 'not found' in error_msg or 'could not be found' in error_msg \
62-
or 'resource not found' in error_msg:
63-
error_type = AladdinUserFaultType.AzureResourceNotFound
64-
if 'storage_account' in error_msg or 'storage account' in error_msg:
65-
error_type = AladdinUserFaultType.StorageAccountNotFound
66-
elif 'resource_group' in error_msg or 'resource group' in error_msg:
67-
error_type = AladdinUserFaultType.ResourceGroupNotFound
68-
elif 'pattern' in error_msg or 'is not a valid value' in error_msg or 'invalid' in error_msg:
69-
error_type = AladdinUserFaultType.InvalidParameterValue
70-
if 'jmespath_type' in error_msg:
71-
error_type = AladdinUserFaultType.InvalidJMESPathQuery
72-
elif 'datetime_type' in error_msg:
73-
error_type = AladdinUserFaultType.InvalidDateTimeArgumentValue
74-
elif '--output' in error_msg:
75-
error_type = AladdinUserFaultType.InvalidOutputType
76-
elif 'resource_group' in error_msg:
77-
error_type = AladdinUserFaultType.InvalidResourceGroupName
78-
elif 'storage_account' in error_msg:
79-
error_type = AladdinUserFaultType.InvalidAccountName
80-
elif "validation error" in error_msg:
81-
error_type = AladdinUserFaultType.ValidationError
82-
83-
return error_type.value
84-
85-
8613
class CommandRecommender: # pylint: disable=too-few-public-methods
8714
"""Recommend a command for user when user's command fails.
88-
It combines Aladdin recommendations and examples in help files."""
15+
It uses examples from help files to provide recommendations."""
8916

9017
def __init__(self, command, parameters, extension, error_msg, cli_ctx):
9118
"""
@@ -107,8 +34,6 @@ def __init__(self, command, parameters, extension, error_msg, cli_ctx):
10734
self.cli_ctx = cli_ctx
10835
# the item is a dict with the form {'command': #, 'description': #}
10936
self.help_examples = []
110-
# the item is a dict with the form {'command': #, 'description': #, 'link': #}
111-
self.aladdin_recommendations = []
11237

11338
def set_help_examples(self, examples):
11439
"""Set help examples.
@@ -119,89 +44,10 @@ def set_help_examples(self, examples):
11944

12045
self.help_examples.extend(examples)
12146

122-
def _set_aladdin_recommendations(self): # pylint: disable=too-many-locals
123-
"""Set Aladdin recommendations.
124-
Call the API, parse the response and set aladdin_recommendations.
125-
"""
126-
127-
import hashlib
128-
import json
129-
import requests
130-
from requests import RequestException
131-
from http import HTTPStatus
132-
from azure.cli.core import __version__ as version
133-
134-
api_url = 'https://app.aladdin.microsoft.com/api/v1.0/suggestions'
135-
correlation_id = telemetry._session.correlation_id # pylint: disable=protected-access
136-
subscription_id = telemetry._get_azure_subscription_id() # pylint: disable=protected-access
137-
event_id = telemetry._session.event_id # pylint: disable=protected-access
138-
# Used for DDOS protection and rate limiting
139-
user_id = telemetry._get_user_azure_id() # pylint: disable=protected-access
140-
hashed_user_id = hashlib.sha256(user_id.encode('utf-8')).hexdigest()
141-
142-
headers = {
143-
'Content-Type': 'application/json',
144-
'X-UserId': hashed_user_id
145-
}
146-
context = {
147-
'versionNumber': version,
148-
'errorType': get_error_type(self.error_msg)
149-
}
150-
151-
if telemetry.is_telemetry_enabled():
152-
if correlation_id:
153-
context['correlationId'] = correlation_id
154-
if subscription_id:
155-
context['subscriptionId'] = subscription_id
156-
if event_id:
157-
context['eventId'] = event_id
158-
159-
parameters = self._normalize_parameters(self.parameters)
160-
parameters = [item for item in set(parameters) if item not in ['--debug', '--verbose', '--only-show-errors']]
161-
query = {
162-
"command": self.command,
163-
"parameters": ','.join(parameters)
164-
}
165-
166-
response = None
167-
try:
168-
response = requests.get(
169-
api_url,
170-
params={
171-
'query': json.dumps(query),
172-
'clientType': 'AzureCli',
173-
'context': json.dumps(context)
174-
},
175-
headers=headers,
176-
timeout=1)
177-
telemetry.set_debug_info('AladdinResponseTime', response.elapsed.total_seconds())
178-
179-
except RequestException as ex:
180-
logger.debug('Recommendation requests.get() exception: %s', ex)
181-
telemetry.set_debug_info('AladdinException', ex.__class__.__name__)
182-
183-
recommendations = []
184-
if response and response.status_code == HTTPStatus.OK:
185-
for result in response.json():
186-
# parse the response to get the raw command
187-
raw_command = 'az {} '.format(result['command'])
188-
for parameter, placeholder in zip(result['parameters'].split(','), result['placeholders'].split('♠')):
189-
raw_command += '{} {}{}'.format(parameter, placeholder, ' ' if placeholder else '')
190-
191-
# format the recommendation
192-
recommendation = {
193-
'command': raw_command.strip(),
194-
'description': result['description'],
195-
'link': result['link']
196-
}
197-
recommendations.append(recommendation)
198-
199-
self.aladdin_recommendations.extend(recommendations)
200-
20147
def provide_recommendations(self):
20248
"""Provide recommendations when a command fails.
20349
204-
The recommendations are either from Aladdin service or CLI help examples,
50+
The recommendations are from CLI help examples,
20551
which include both commands and reference links along with their descriptions.
20652
20753
:return: The decorated recommendations
@@ -273,14 +119,7 @@ def replace_param_values(command): # pylint: disable=unused-variable
273119
if self.cli_ctx and self.cli_ctx.config.get('core', 'error_recommendation', 'on').upper() == 'OFF':
274120
return []
275121

276-
# get recommendations from Aladdin service
277-
if not self._disable_aladdin_service():
278-
self._set_aladdin_recommendations()
279-
280-
# recommendations are either all from Aladdin or all from help examples
281-
recommendations = self.aladdin_recommendations
282-
if not recommendations:
283-
recommendations = self.help_examples
122+
recommendations = self.help_examples
284123

285124
# sort the recommendations by parameter matching, get the top 3 recommended commands
286125
recommendations = sort_recommendations(recommendations)[:3]
@@ -305,8 +144,6 @@ def replace_param_values(command): # pylint: disable=unused-variable
305144

306145
# add reference link as a recommendation
307146
decorated_link = [(Style.HYPERLINK, OVERVIEW_REFERENCE)]
308-
if self.aladdin_recommendations:
309-
decorated_link = [(Style.HYPERLINK, self.aladdin_recommendations[0]['link'])]
310147

311148
decorated_description = [(Style.SECONDARY, 'Read more about the command in reference docs')]
312149
decorated_recommendations.append((decorated_link, decorated_description))
@@ -319,49 +156,11 @@ def replace_param_values(command): # pylint: disable=unused-variable
319156
def _set_recommended_command_to_telemetry(self, raw_commands):
320157
"""Set the recommended commands to Telemetry
321158
322-
Aladdin recommended commands and commands from CLI help examples are
323-
set to different properties in Telemetry.
324-
325159
:param raw_commands: The recommended raw commands
326160
:type raw_commands: list
327161
"""
328162

329-
if self.aladdin_recommendations:
330-
telemetry.set_debug_info('AladdinRecommendCommand', ';'.join(raw_commands))
331-
else:
332-
telemetry.set_debug_info('ExampleRecommendCommand', ';'.join(raw_commands))
333-
334-
def _disable_aladdin_service(self):
335-
"""Decide whether to disable aladdin request when a command fails.
336-
337-
The possible cases to disable it are:
338-
1. CLI context is missing
339-
2. In air-gapped clouds
340-
3. In testing environments
341-
4. In autocomplete mode
342-
343-
:return: whether Aladdin service need to be disabled or not
344-
:type: bool
345-
"""
346-
347-
from azure.cli.core.cloud import CLOUDS_FORBIDDING_ALADDIN_REQUEST
348-
349-
# CLI is not started well
350-
if not self.cli_ctx or not self.cli_ctx.cloud:
351-
return True
352-
353-
# for air-gapped clouds
354-
if self.cli_ctx.cloud.name in CLOUDS_FORBIDDING_ALADDIN_REQUEST:
355-
return True
356-
357-
# for testing environments
358-
if self.cli_ctx.__class__.__name__ == 'DummyCli':
359-
return True
360-
361-
if self.cli_ctx.data['completer_active']:
362-
return True
363-
364-
return False
163+
telemetry.set_debug_info('ExampleRecommendCommand', ';'.join(raw_commands))
365164

366165
def _normalize_parameters(self, args):
367166
"""Normalize a parameter list.

src/azure-cli-core/azure/cli/core/parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def error(self, message):
169169
from azure.cli.core.util import QUERY_REFERENCE
170170
az_error.set_recommendation(QUERY_REFERENCE)
171171
elif recommendations:
172-
az_error.set_aladdin_recommendation(recommendations)
172+
az_error.set_example_recommendation(recommendations)
173173
az_error.print_error()
174174
az_error.send_telemetry()
175175
self.exit(2)
@@ -324,7 +324,7 @@ def _check_value(self, action, value):
324324
recommender.set_help_examples(self.get_examples(command_name_inferred))
325325
recommendations = recommender.provide_recommendations()
326326
if recommendations:
327-
az_error.set_aladdin_recommendation(recommendations)
327+
az_error.set_example_recommendation(recommendations)
328328

329329
# remind user to check extensions if we can not find a command to recommend
330330
if isinstance(az_error, CommandNotFoundError) \

0 commit comments

Comments
 (0)