def set_up_containerapp_resiliency_yaml()

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