Skip to content

Commit c34d777

Browse files
[Containerapp] updating min-replica check for az containerapp function keys commands and modifications to app-insights query for az containerapp function invocations (#9431)
1 parent c984143 commit c34d777

File tree

5 files changed

+46
-10
lines changed

5 files changed

+46
-10
lines changed

src/containerapp/HISTORY.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Release History
44
===============
55
upcoming
66
++++++
7+
* 'az containerapp function invocations': Update application insights query
8+
* 'az containerapp function keys': Update minimum replica check
79

810
1.3.0b1
911
++++++

src/containerapp/azext_containerapp/_utils.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,17 @@ def create_acrpull_role_assignment_if_needed(cmd, registry_server, registry_iden
835835
time.sleep(5)
836836

837837

838+
def get_min_replicas_from_revision(cmd, resource_group_name, container_app_name, revision_name):
839+
revision_def = ContainerAppClient.show_revision(
840+
cmd=cmd,
841+
resource_group_name=resource_group_name,
842+
container_app_name=container_app_name,
843+
name=revision_name
844+
)
845+
min_replicas = safe_get(revision_def, "properties", "template", "scale", "minReplicas", default=None)
846+
return min_replicas
847+
848+
838849
def get_random_replica(cmd, resource_group_name, container_app_name, revision_name):
839850
logger.debug(f"Getting random replica for container app: name='{container_app_name}', resource_group='{resource_group_name}', revision='{revision_name}'")
840851

@@ -851,6 +862,18 @@ def get_random_replica(cmd, resource_group_name, container_app_name, revision_na
851862

852863
if not replicas:
853864
logger.debug(f"No replicas found for revision '{revision_name}' - unable to proceed")
865+
logger.debug(f"checking min replica count for revision='{revision_name}'")
866+
867+
min_replicas = get_min_replicas_from_revision(
868+
cmd,
869+
resource_group_name,
870+
container_app_name,
871+
revision_name
872+
)
873+
if min_replicas is None or min_replicas == 0:
874+
logger.debug(f"The revision '{revision_name}' has minReplicas set to 0.")
875+
raise CLIError(f"The revision '{revision_name}' has minReplicas set to 0. Ensure that there is at least one replica. To update minimum replica: Run 'az containerapp update --name {container_app_name} --resource-group {resource_group_name} --min-replica 1'")
876+
854877
raise CLIError(f"No replicas found for revision '{revision_name}' of container app '{container_app_name}'.")
855878

856879
# Filter replicas by running state

src/containerapp/azext_containerapp/_validators.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ def validate_revision_and_get_name(cmd, resource_group_name, container_app_name,
318318
if not provided_revision_name:
319319
logger.debug("No revision name provided for multiple revision mode container app")
320320
raise ValidationError("Revision name is required when active revision mode is not 'single'.")
321-
return provided_revision_name
321+
return provided_revision_name, active_revision_mode
322322
if not provided_revision_name:
323323
logger.debug("No revision name provided - attempting to determine latest revision")
324324
revision_name = safe_get(containerapp_def, "properties", "latestRevisionName")
@@ -331,9 +331,9 @@ def validate_revision_and_get_name(cmd, resource_group_name, container_app_name,
331331
if not revision_name or revision_name is None:
332332
logger.debug("Could not determine any revision name from container app properties")
333333
raise ValidationError("Could not determine the latest revision name. Please provide --revision.")
334-
return revision_name
334+
return revision_name, active_revision_mode
335335
logger.debug("Using provided revision name: '%s'", provided_revision_name)
336-
return provided_revision_name
336+
return provided_revision_name, active_revision_mode
337337

338338

339339
def validate_functionapp_kind(cmd, resource_group_name, container_app_name):

src/containerapp/azext_containerapp/containerapp_function_keys_decorator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def validate_common_arguments(self):
5858
)
5959

6060
# Validate revision and get the appropriate revision name
61-
revision_name = validate_revision_and_get_name(
61+
revision_name, _ = validate_revision_and_get_name(
6262
cmd=self.cmd,
6363
resource_group_name=resource_group_name,
6464
container_app_name=name,

src/containerapp/azext_containerapp/containerapp_functions_decorator.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def validate_common_arguments(self):
7272
)
7373

7474
# Validate revision and get the appropriate revision name
75-
revision_name = validate_revision_and_get_name(
75+
revision_name, _ = validate_revision_and_get_name(
7676
cmd=self.cmd,
7777
resource_group_name=resource_group_name,
7878
container_app_name=name,
@@ -170,6 +170,10 @@ class ContainerAppFunctionInvocationsDecorator(ContainerAppFunctionsDecorator):
170170

171171
APP_INSIGHTS_API_VERSION = "2018-04-20"
172172

173+
def __init__(self, cmd, client, raw_parameters, models):
174+
super().__init__(cmd, client, raw_parameters, models)
175+
self.active_revision_mode = None
176+
173177
def validate_arguments(self):
174178
"""Validate arguments required for function invocation operations"""
175179
validate_basic_arguments(
@@ -185,14 +189,17 @@ def validate_arguments(self):
185189
)
186190

187191
revision_name = self.get_argument_revision_name()
188-
revision_name = validate_revision_and_get_name(
192+
revision_name, active_revision_mode = validate_revision_and_get_name(
189193
cmd=self.cmd,
190194
resource_group_name=self.get_argument_resource_group_name(),
191195
container_app_name=self.get_argument_container_app_name(),
192196
provided_revision_name=revision_name
193197
)
198+
194199
# Update the revision name with the validated value
195200
self.set_argument_revision_name(revision_name)
201+
# Store active revision mode for use in query building
202+
self.active_revision_mode = active_revision_mode
196203
self.validate_function_name_requirement()
197204

198205
def _get_app_insights_id(self, resource_group_name, container_app_name, revision_name):
@@ -267,12 +274,14 @@ def get_summary(self):
267274
# Fetch the app insights resource app id
268275
app_id = self._get_app_insights_id(resource_group_name, container_app_name, revision_name)
269276

270-
# Use application insights query to get function invocations summary
277+
# Set revision_name to empty string for single mode, keep it for multiple mode
278+
revision_name = "" if self.active_revision_mode.lower() == "single" else revision_name
279+
271280
invocation_summary_query = (
272281
f"requests | extend functionNameFromCustomDimension = tostring(customDimensions['faas.name']) "
273282
f"| where timestamp >= ago({timespan}) "
274283
f"| where cloud_RoleName =~ '{container_app_name}' "
275-
f"| where cloud_RoleInstance contains '{revision_name}' "
284+
f"| where isempty(\"{revision_name}\") or cloud_RoleInstance contains '{revision_name}' "
276285
f"| where operation_Name =~ '{function_name}' or functionNameFromCustomDimension =~ '{function_name}' "
277286
f"| summarize SuccessCount = coalesce(countif(success == true), 0), ErrorCount = coalesce(countif(success == false), 0)"
278287
)
@@ -299,14 +308,16 @@ def get_traces(self):
299308
# Fetch the app insights resource app id
300309
app_id = self._get_app_insights_id(resource_group_name, container_app_name, revision_name)
301310

302-
# Use application insights query to get function invocations traces
311+
# Set revision_name to empty string for single mode, keep it for multiple mode
312+
revision_name = "" if self.active_revision_mode.lower() == "single" else revision_name
313+
303314
invocation_traces_query = (
304315
f"requests | extend functionNameFromCustomDimension = tostring(customDimensions['faas.name']) "
305316
f"| project timestamp, id, operation_Name, success, resultCode, duration, operation_Id, functionNameFromCustomDimension, "
306317
f"cloud_RoleName, cloud_RoleInstance, invocationId=coalesce(tostring(customDimensions['InvocationId']), tostring(customDimensions['faas.invocation_id'])) "
307318
f"| where timestamp > ago({timespan}) "
308319
f"| where cloud_RoleName =~ '{container_app_name}' "
309-
f"| where cloud_RoleInstance contains '{revision_name}' "
320+
f"| where isempty(\"{revision_name}\") or cloud_RoleInstance contains '{revision_name}' "
310321
f"| where operation_Name =~ '{function_name}' or functionNameFromCustomDimension =~ '{function_name}' "
311322
f"| order by timestamp desc | take {limit} "
312323
f"| project timestamp, success, resultCode, durationInMilliSeconds=duration, invocationId, operationId=operation_Id, operationName=operation_Name, functionNameFromCustomDimension "

0 commit comments

Comments
 (0)