Skip to content

Commit

Permalink
Merge pull request #25 from aziontech/improve_complex_conf_converter
Browse files Browse the repository at this point in the history
[ENG-33150] chore: improve complex conf converter
  • Loading branch information
helio-neto authored Mar 3, 2025
2 parents 55f4f1c + 0bfbd3f commit 36163c9
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 86 deletions.
60 changes: 33 additions & 27 deletions src/akamai/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def process_rules(
main_setting_name (str): The main setting name for Azion configuration.
origin_hostname (str): The origin hostname for Azion configuration.
"""
context = {}
if isinstance(rules, str):
logging.debug("Rules attribute is a string reference. Converting to JSON content.")
rules = clean_and_parse_json(rules)
Expand All @@ -105,10 +106,10 @@ def process_rules(
logging.info(f"[Akamai Rules] Found {len(behaviors)} behaviors and {len(children)} children for rule: '{normalized_name}'")

if len(behaviors) > 0:
process_rule_behaviors(azion_resources, rules, main_setting_name, origin_hostname, 0, normalized_name)
context = process_rule_behaviors(azion_resources, rules, main_setting_name, origin_hostname, 0, normalized_name)

if len(children) > 0:
process_rule_children(azion_resources, children, main_setting_name, origin_hostname, 0, normalized_name)
process_rule_children(azion_resources, children, main_setting_name, origin_hostname, 0, normalized_name, context)

elif isinstance(rules, list):
logging.debug("Rules provided as a list. Processing each rule.")
Expand All @@ -120,10 +121,10 @@ def process_rules(
logging.info(f"[Akamai Rules] Found {len(behaviors)} behaviors and {len(children)} children for rule: '{normalized_name}'")

if behaviors:
process_rule_behaviors(azion_resources, rule, main_setting_name, origin_hostname, index, normalized_name)
context = process_rule_behaviors(azion_resources, rule, main_setting_name, origin_hostname, index, normalized_name)

if len(children) > 0:
process_rule_children(azion_resources, children, main_setting_name, origin_hostname, index, normalized_name)
process_rule_children(azion_resources, children, main_setting_name, origin_hostname, index, normalized_name, context)

else:
logging.warning(f"[Akamai Rules] Unexpected type for rules: {type(rules)}. Skipping rule processing.")
Expand All @@ -138,7 +139,7 @@ def process_rule_behaviors(
origin_hostname: str,
index: int,
normalized_name: str
) -> List[Dict[str, Any]]:
) -> Dict[str, Any]:
"""
Processes the list of behaviors rules and converts them into Azion resources.
Expand Down Expand Up @@ -166,9 +167,15 @@ def process_rule_behaviors(

for behavior in behaviors:
behavior_name = behavior.get("name")
if behavior_name == "caching": # Cache Settings

if behavior_name == "origin": # Origin
origin = create_origin(azion_resources, behavior, main_setting_name, origin_hostname, context["rule_name"])
if origin:
azion_resources.append(origin)
context["origin"] = origin
elif behavior_name == "caching": # Cache Settings
cache_setting.append(behavior)
cache_setting = create_cache_setting(azion_resources, cache_setting, main_setting_name, context["rule_name"])
cache_setting = create_cache_setting(azion_resources, cache_setting, main_setting_name, context["rule_name"], context)
if cache_setting:
azion_resources.append(cache_setting)
context["cache_setting"] = cache_setting
Expand All @@ -187,15 +194,11 @@ def process_rule_behaviors(
resources = azion_resources.get_azion_resources()
main_settings["attributes"]["edge_application"]["application_acceleration"] = True
resources[index_main_settings] = main_settings
elif behavior_name == "origin": # Origin
origin = create_origin(azion_resources, behavior, main_setting_name, origin_hostname, context["rule_name"])
if origin:
azion_resources.append(origin)
context["origin"] = origin

azion_resources.extend(create_rule_engine(azion_resources, rule, context, context["rule_name"]))

logging.info(f"[Akamai Rules] Processing behaviors for rules '{normalized_name}'. Finished.")
return context


def process_rule_children(
Expand All @@ -204,7 +207,8 @@ def process_rule_children(
main_setting_name: str,
origin_hostname: str,
parent_rule_index: int,
parent_rule_name: str
parent_rule_name: str,
parent_context: Dict[str, Any]
) -> List[Dict[str, Any]]:
"""
Processes the list of children rules and converts them into Azion resources.
Expand All @@ -223,6 +227,7 @@ def process_rule_children(
context = {}
context["parent_rule_index"] = parent_rule_index
context["parent_rule_name"] = parent_rule_name
context["parent_context"] = parent_context
context["main_setting_name"] = main_setting_name

# Rules Processing
Expand All @@ -241,42 +246,43 @@ def process_rule_children(
try:
behaviors = rule.get("behaviors", [])
for behavior in behaviors:
if behavior.get("name") == "caching":
cache_setting = create_cache_setting(azion_resources, behaviors, main_setting_name, rule_name)
behavior_name = behavior.get("name")
if behavior_name == "origin":
origin_setting = create_origin(azion_resources, behavior, main_setting_name, origin_hostname, sanitize_name(rule_name))
if origin_setting:
logging.info(f"Origin setting created for rule: {rule_name}")
azion_resources.append(origin_setting)
context["origin"] = origin_setting

elif behavior_name == "caching":
cache_setting = create_cache_setting(azion_resources, behaviors, main_setting_name, rule_name, context)
if cache_setting:
logging.info(f"[Akamai Rules][Children] Cache setting created for rule: {rule_name}")
azion_resources.append(cache_setting)
context["cache_setting"] = cache_setting

if behavior.get("name") == "imageManager":
elif behavior.get("name") == "imageManager":
idx, main_settings = azion_resources.query_azion_resource_by_type('azion_edge_application_main_setting')
if main_settings:
main_settings["attributes"]["edge_application"]["image_optimization"] = True
resources = azion_resources.get_azion_resources()
resources[idx] = main_settings

if behavior.get("name") == "allowPost":
elif behavior.get("name") == "allowPost":
idx, main_settings = azion_resources.query_azion_resource_by_type('azion_edge_application_main_setting')
if main_settings:
resources = azion_resources.get_azion_resources()
main_settings["attributes"]["edge_application"]["application_acceleration"] = True
resources[idx] = main_settings

if behavior.get("name") == "origin":
origin_setting = create_origin(azion_resources, behaviors[0], main_setting_name, origin_hostname, sanitize_name(rule_name))
if origin_setting:
logging.info(f"Origin setting created for rule: {rule_name}")
azion_resources.append(origin_setting)
context["origin"] = origin_setting

if behavior.get("name") == "webApplicationFirewall":
elif behavior.get("name") == "webApplicationFirewall":
waf_rule = create_waf_rule(azion_resources, behavior)
if waf_rule:
logging.info(f"WAF rule created for rule: {rule_name}")
azion_resources.append(waf_rule)
context["waf"] = waf_rule

if behavior.get("name") == "baseDirectory":
elif behavior.get("name") == "baseDirectory":
idx, origin = azion_resources.query_azion_resource_by_type('azion_edge_application_origin', sanitize_name(rule_name))
if origin:
origin["attributes"]["origin"]["origin_path"] = behavior.get("options", {}).get("value", "")
Expand All @@ -289,7 +295,7 @@ def process_rule_children(
children = rule.get("children", [])
if len(children) > 0:
logging.info(f"[Akamai Rules][Children] Rule '{rule_name}' has {len(children)} inner children rules. Processing...")
process_rule_children(azion_resources, children, main_setting_name, origin_hostname, index, rule_name)
process_rule_children(azion_resources, children, main_setting_name, origin_hostname, index, rule_name, context)

except ValueError as e:
logging.error(f"[Akamai Rules][Children] Error processing rule engine for rule {rule_name}: {e}")
Expand Down
18 changes: 15 additions & 3 deletions src/akamai/converter_cache_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def create_cache_setting(
azion_resources: AzionResource,
rules: List[Dict[str, Any]],
main_setting_name: str,
cache_name: Optional[str] = None
cache_name: Optional[str] = None,
context: Dict[str, Any] = {}
) -> Optional[Dict[str, Any]]:
"""
Creates a single Azion cache setting resource.
Expand All @@ -59,6 +60,7 @@ def create_cache_setting(
rules (List[Dict[str, Any]]): List of rules extracted from Akamai configuration.
main_setting_name (str): Name of the main Azion edge application resource.
cache_name (Optional[str]): Name of the cache setting resource.
context (Dict[str, Any]): Context dictionary to store intermediate results.
Returns:
Optional[Dict[str, Any]]: Azion-compatible cache setting resource.
Expand Down Expand Up @@ -113,9 +115,19 @@ def create_cache_setting(

#depends_on
depends_on = [f"azion_edge_application_main_setting.{main_setting_name}"]
_, origin = azion_resources.query_azion_resource_by_type("azion_edge_application_origin", name)
origin = context.get("origin")
if origin:
depends_on.append(f"azion_edge_application_origin.{name}")
depends_on.append(f"azion_edge_application_origin.{origin.get('name')}")
else:
logging.warning("No origin found in context. Attempting to query Azion resources...")
_, origin = azion_resources.query_azion_resource_by_type("azion_edge_application_origin", name, match="prefix")
if origin:
depends_on.append(f"azion_edge_application_origin.{origin.get('name')}")
else:
logging.warning(f"No origin found for rule: {name}... Using fallback origin")
_, origin = azion_resources.query_azion_resource_by_type("azion_edge_application_origin", match="prefix")
if origin:
depends_on.append(f"azion_edge_application_origin.{origin.get('name')}")

# Construct the cache setting resource
cache_setting = {
Expand Down
68 changes: 44 additions & 24 deletions src/akamai/converter_rules_engine.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
import random
from typing import Dict, List, Any, Set, Tuple
from typing import Dict, List, Any, Set, Tuple, Optional
from azion_resources import AzionResource
from akamai.mapping import MAPPING
from akamai.utils import (
Expand Down Expand Up @@ -32,7 +32,7 @@ def create_rule_engine(
azion_resources: AzionResource,
rule: Dict[str, Any],
context: Dict[str, Any],
name: str = None
name: str = None,
) -> List[Dict[str, Any]]:
"""
Create a rule engine resource from Akamai rule data.
Expand Down Expand Up @@ -77,12 +77,17 @@ def create_rule_engine(
depends_on = [f"azion_edge_application_main_setting.{main_setting_name}"]
depends_on.extend(list(depends_on_behaviors))

request_behaviors = list(
filter(lambda behavior: behavior.get('phase', 'request') == 'request', azion_behaviors)
)
response_behaviors = list(
filter(lambda behavior: behavior.get('phase', 'request') == 'response', azion_behaviors)
)
# Handling behaviors by phase
request_behaviors = []
response_behaviors = []
for behavior in azion_behaviors:
if behavior.get('phase', 'both') == 'both':
request_behaviors.append(behavior)
response_behaviors.append(behavior)
elif behavior.get('phase', 'request') == 'request':
request_behaviors.append(behavior)
elif behavior.get('phase', 'request') == 'response':
response_behaviors.append(behavior)

# Create request phase rule
if len(request_behaviors) > 0:
Expand All @@ -92,8 +97,9 @@ def create_rule_engine(
azion_criteria,
request_behaviors,
depends_on)
resources.append(resource)
logging.info(f"[rules_engine] Rule engine resource created for rule: '{rule_name}'")
if resource:
resources.append(resource)
logging.info(f"[rules_engine] Rule engine resource created for rule: '{rule_name}'")

# Create response phase rule
if len(response_behaviors) > 0:
Expand All @@ -103,8 +109,9 @@ def create_rule_engine(
azion_criteria,
response_behaviors,
depends_on)
resources.append(resource)
logging.info(f"[rules_engine] Rule engine resource created for rule: '{rule_name}'")
if resource:
resources.append(resource)
logging.info(f"[rules_engine] Rule engine resource created for rule: '{rule_name}'")

# Enable image optimization if necessary
if "imageManager" in behaviors_names:
Expand All @@ -127,7 +134,7 @@ def assemble_request_rule(
azion_criteria: Dict[str, Any],
request_behaviors: List[Dict[str, Any]],
depends_on: List[str]
) -> Dict[str, Any]:
) -> Optional[Dict[str, Any]]:
"""
Create a rule engine resource from Akamai rule data.
Expand Down Expand Up @@ -162,9 +169,13 @@ def assemble_request_rule(
}

# Only add criteria if we have entries
if azion_criteria:
criteria = azion_criteria.get("request",{}) if azion_criteria.get("request",{}) else azion_criteria.get("request_default",{})
criteria = azion_criteria.get("request", None)
if criteria:
resource["attributes"]["results"]["criteria"] = criteria
else:
logging.warning(f"[rules_engine][assemble_request_rule] No criteria found for rule: '{rule_name}'. Skipping.")
resource = None

return resource

def assemble_response_rule(
Expand All @@ -174,7 +185,7 @@ def assemble_response_rule(
azion_criteria: Dict[str, Any],
behaviors: List[Dict[str, Any]],
depends_on: List[str]
) -> Dict[str, Any]:
) -> Optional[Dict[str, Any]]:
"""
Create a rule engine resource from Akamai rule data.
Expand Down Expand Up @@ -202,13 +213,18 @@ def assemble_response_rule(
if len(criterias) == 1:
selected_criteria = azion_criteria.get("response")
else:
selection = []
for criteria in criterias:
for behavior in behaviors:
if criteria.get("name", "") == behavior.get('name'):
selected_criteria = {"entries": [criteria]}
if criteria.get("name", "") == behavior.get('name') or \
criteria.get("phase", "both") != "request":
selection.append(criteria)
break
selected_criteria = {"entries": selection}
else:
selected_criteria = azion_criteria.get("response_default")
#selected_criteria = azion_criteria.get("response_default")
logging.warning(f"[rules_engine][assemble_response_rule] No criteria found for rule: '{rule_name}'. Skipping.")
return None

rule_description = rule.get("comments", "").replace("\n", " ").replace("\r", " ").replace("\"", "'")
resource = {
Expand All @@ -227,7 +243,7 @@ def assemble_response_rule(
}

# Only add criteria if we have entries
if selected_criteria:
if len(selected_criteria) > 0:
resource["attributes"]["results"]["criteria"] = selected_criteria
return resource

Expand Down Expand Up @@ -460,10 +476,10 @@ def behavior_cache_setting(
cache_setttings = context.get("cache_setting")
if cache_setttings is None:
_, cache_setttings = azion_resources.query_azion_resource_by_type(
'azion_edge_application_cache_setting', sanitize_name(parent_rule_name))
'azion_edge_application_cache_setting', sanitize_name(parent_rule_name), match="prefix")
if cache_setttings is None:
_, cache_setttings = azion_resources.query_azion_resource_by_type(
'azion_edge_application_cache_setting', sanitize_name(rule_name))
'azion_edge_application_cache_setting', sanitize_name(rule_name), match="prefix")

if cache_setttings:
cache_settings_name = cache_setttings.get("name")
Expand Down Expand Up @@ -506,11 +522,11 @@ def behavior_set_origin(
if origin_settings is None:
_, origin_settings = azion_resources.query_azion_resource_by_type(
"azion_edge_application_origin",
sanitize_name(parent_rule_name))
sanitize_name(parent_rule_name), match="prefix")
if origin_settings is None:
_, origin_settings = azion_resources.query_azion_resource_by_type(
"azion_edge_application_origin",
sanitize_name(rule_name))
sanitize_name(rule_name), match="prefix")
if origin_settings is None:
origin_settings = azion_resources.query_azion_origin_by_address(options.get("hostname", ""))

Expand All @@ -523,6 +539,8 @@ def behavior_set_origin(
"enabled": True,
"target": {"target": origin_settings_ref + ".id"},
"description": f"Set origin to {options.get('name', '')}",
"phase": "request",
"akamai_behavior": "setOrigin"
}

return azion_behavior, origin_settings_ref
Expand Down Expand Up @@ -698,6 +716,8 @@ def process_behaviors(
"enabled": True,
"description": f"Add host header to {trueClientIpHeader}",
"target": { "target": '"' + f'{trueClientIpHeader}: ' + "$${remote_addr}" + '"' },
"phase": "request",
"akamai_behavior": "trueClientIpHeader"
}

unique_key = behavior_key(azion_behavior)
Expand Down
Loading

0 comments on commit 36163c9

Please sign in to comment.