in src/containerapp/azext_containerapp/containerapp_resiliency_decorator.py [0:0]
def set_up_containerapp_resiliency_yaml(self, file_name):
containerapp_def = ContainerAppsResiliencyModel
if self.get_argument_tcp_retry_max_connect_attempts() or self.get_argument_circuit_breaker_consecutive_errors()\
or self.get_argument_circuit_breaker_interval() or self.get_argument_circuit_breaker_max_ejection() or \
self.get_argument_tcp_connection_pool_max_connections() or \
self.get_argument_http_connection_pool_http1_max_pending_req() \
or self.get_argument_http_connection_pool_http2_max_req() or self.get_argument_timeout_response_in_seconds() \
or self.get_argument_timeout_connection_in_seconds() or self.get_argument_http_retry_max() \
or self.get_argument_http_retry_delay_in_milliseconds() or self.get_argument_http_retry_interval_in_milliseconds() \
or self.get_argument_http_retry_status_codes() or self.get_argument_http_retry_errors():
not self.get_argument_disable_warnings() and logger.warning(
'Additional flags were passed along with --yaml. These flags will be ignored, and the configuration '
'defined in the yaml will be used instead')
yaml_containerapps_resiliency = load_yaml_file(file_name)
if not isinstance(yaml_containerapps_resiliency, dict): # pylint: disable=unidiomatic-typecheck
raise ValidationError('Invalid YAML provided. Please supply a valid YAML spec.')
if yaml_containerapps_resiliency.get('type') and yaml_containerapps_resiliency.get('type').lower() != "microsoft.app/containerapps/resiliencypolicies":
raise ValidationError('Containerapp resiliency type must be \"Microsoft.App/containerApps/resiliencyPolicies\"')
if yaml_containerapps_resiliency.get('name') and yaml_containerapps_resiliency.get('name').lower() != self.get_argument_name().lower():
logger.warning(
'The app name provided in the --yaml file "{}" does not match the one provided in the --name flag "{}". The one provided in the --yaml file will be used.'.format(
yaml_containerapps_resiliency.get('name'), self.get_argument_name()))
self.set_argument_name(yaml_containerapps_resiliency.get('name'))
if yaml_containerapps_resiliency.get('containerAppName') and yaml_containerapps_resiliency.get('containerAppName').lower() != self.get_argument_container_app_name().lower():
logger.warning(
'The containerapp name provided in the --yaml file "{}" does not match the one provided in the --container-app-name flag "{}". The one provided in the --yaml file will be used.'.format(
yaml_containerapps_resiliency.get('containerAppName'), self.get_argument_container_app_name()))
self.set_argument_container_app_name(yaml_containerapps_resiliency.get('containerAppName'))
# Deserialize the yaml into a ContainerAppsResiliency object. Need this since we're not using SDK
try:
deserializer = create_deserializer(self.models)
containerapp_def = deserializer('AppResiliency', yaml_containerapps_resiliency)
except DeserializationError as ex:
raise ValidationError('Invalid YAML provided. Please supply a valid YAML spec.') from ex
containerapp_def = _convert_object_from_snake_to_camel_case(
_object_to_dict(containerapp_def))
containerapp_def = process_containerapp_resiliency_yaml(containerapp_def)
# Remove "additionalProperties" and read-only attributes that are introduced in the deserialization. Need this since we're not using SDK
_remove_additional_attributes(containerapp_def)
_remove_readonly_attributes(containerapp_def)
containerapp_def = clean_null_values(containerapp_def)
# Now we just add defaults where required
# Retries
http_retry_policy = safe_get(containerapp_def, 'properties', 'httpRetryPolicy')
if http_retry_policy and ('maxRetries' in http_retry_policy or 'retryBackOff' in http_retry_policy or 'matches' in http_retry_policy):
http_retry_policy['maxRetries'] = http_retry_policy.get('maxRetries', DEFAULT_HTTP_RETRY_MAX)
retry_backoff = safe_get(http_retry_policy, 'retryBackOff')
if retry_backoff and ('initialDelayInMilliseconds' in retry_backoff or 'maxIntervalInMilliseconds' in retry_backoff):
retry_backoff['initialDelayInMilliseconds'] = retry_backoff.get('initialDelayInMilliseconds', DEFAULT_HTTP_RETRY_DELAY_IN_MILLISECONDS)
retry_backoff['maxIntervalInMilliseconds'] = retry_backoff.get('maxIntervalInMilliseconds', DEFAULT_HTTP_RETRY_INTERVAL_IN_MILLISECONDS)
else:
retry_backoff = {
"initialDelayInMilliseconds": DEFAULT_HTTP_RETRY_DELAY_IN_MILLISECONDS,
"maxIntervalInMilliseconds": DEFAULT_HTTP_RETRY_INTERVAL_IN_MILLISECONDS
}
http_retry_policy['retryBackOff'] = retry_backoff
matches = safe_get(http_retry_policy, 'matches')
if matches and 'errors' in matches:
matches['errors'] = matches.get('errors', DEFAULT_HTTP_RETRY_ERRORS)
else:
matches = {
"errors": DEFAULT_HTTP_RETRY_ERRORS
}
http_retry_policy['matches'] = matches
containerapp_def['properties']['httpRetryPolicy'] = http_retry_policy
# Timeouts
timeout_policy = safe_get(containerapp_def, 'properties', 'timeoutPolicy')
if timeout_policy and ('responseTimeoutInSeconds' in timeout_policy or 'connectionTimeoutInSeconds' in timeout_policy):
timeout_policy['responseTimeoutInSeconds'] = timeout_policy.get('responseTimeoutInSeconds', DEFAULT_RESPONSE_TIMEOUT)
timeout_policy['connectionTimeoutInSeconds'] = timeout_policy.get('connectionTimeoutInSeconds', DEFAULT_CONNECTION_TIMEOUT)
containerapp_def['properties']['timeoutPolicy'] = timeout_policy
# Circuit Breaker
circuit_breaker_policy = safe_get(containerapp_def, 'properties', 'circuitBreakerPolicy')
if circuit_breaker_policy and ('consecutiveErrors' in circuit_breaker_policy or 'intervalInSeconds' in circuit_breaker_policy or 'maxEjectionPercent' in circuit_breaker_policy):
circuit_breaker_policy['consecutiveErrors'] = circuit_breaker_policy.get('consecutiveErrors', DEFAULT_CONSECUTIVE_ERRORS)
circuit_breaker_policy['intervalInSeconds'] = circuit_breaker_policy.get('intervalInSeconds', DEFAULT_INTERVAL)
circuit_breaker_policy['maxEjectionPercent'] = circuit_breaker_policy.get('maxEjectionPercent', DEFAULT_MAX_EJECTION)
containerapp_def['properties']['circuitBreakerPolicy'] = circuit_breaker_policy
# HTTP Connection Pool
http_connection_pool = safe_get(containerapp_def, 'properties', 'httpConnectionPool')
if http_connection_pool and ('http1MaxPendingRequests' in http_connection_pool or 'http2MaxRequests' in http_connection_pool):
http_connection_pool['http1MaxPendingRequests'] = http_connection_pool.get('http1MaxPendingRequests', DEFAULT_HTTP1_MAX_PENDING_REQ)
http_connection_pool['http2MaxRequests'] = http_connection_pool.get('http2MaxRequests', DEFAULT_HTTP2_MAX_REQ)
containerapp_def['properties']['httpConnectionPool'] = http_connection_pool
return containerapp_def