Skip to content

Commit

Permalink
feat: Added application segment validation features
Browse files Browse the repository at this point in the history
  • Loading branch information
willguibr committed Oct 2, 2023
1 parent 46025d9 commit 99e8a30
Show file tree
Hide file tree
Showing 5 changed files with 272 additions and 148 deletions.
140 changes: 140 additions & 0 deletions plugins/module_utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,147 @@

import pycountry

def deleteNone(_dict):
"""Delete None values recursively from all of the dictionaries, tuples, lists, sets"""
if isinstance(_dict, dict):
for key, value in list(_dict.items()):
if isinstance(value, (list, dict, tuple, set)):
_dict[key] = deleteNone(value)
elif value is None or key is None:
del _dict[key]
elif isinstance(_dict, (list, set, tuple)):
_dict = type(_dict)(deleteNone(item) for item in _dict if item is not None)
return _dict

# Function to handle application segment port conversion list
def convert_ports_list(obj_list):
if obj_list is None:
return []
r = []
for o in obj_list:
if o.get("from", None) is not None and o.get("to", None) is not None:
r.append("" + o.get("from"))
r.append("" + o.get("to"))
return r


def convert_ports(obj_list):
if obj_list is None:
return []
r = []
for o in obj_list:
if o.get("from", None) is not None and o.get("to", None) is not None:
c = (o.get("from"), o.get("to"))
r.append(c)
return r

def convert_bool_to_str(value, true_value='1', false_value='0'):
"""
Converts a boolean value to its corresponding string representation.
Args:
value (bool or str): The value to be converted.
true_value (str): The string representation for True.
false_value (str): The string representation for False.
Returns:
str: true_value if the value is True, false_value if the value is False, value if it's already a string.
"""
if isinstance(value, bool):
return true_value if value else false_value
return value # if the value is already a string, return it as-is

def convert_str_to_bool(value, true_value='1', false_value='0'):
"""
Converts a string representation of a boolean to an actual boolean.
Args:
value (str): The value to be converted.
true_value (str): The string representation for True.
false_value (str): The string representation for False.
Returns:
bool: True if the value is true_value, False if the value is false_value.
"""
if value == true_value:
return True
elif value == false_value:
return False
return value # if the value isn't recognized, return it as-is

def normalize_app(app):
normalized = app.copy()

# Exclude computed values from the data
computed_values = [
"creation_time", "modified_by", "modified_time", "id",
"config_space", "microtenant_name", "segment_group_name",
"server_groups", "use_in_dr_mode",
"is_incomplete_dr_config", "inspect_traffic_with_zia", "adp_enabled",
]
for attr in computed_values:
normalized.pop(attr, None)

# Convert tcp_keep_alive from string to boolean
if 'tcp_keep_alive' in normalized:
normalized['tcp_keep_alive'] = convert_str_to_bool(normalized['tcp_keep_alive'])

# Convert icmp_access_type to boolean
if 'icmp_access_type' in normalized:
normalized['icmp_access_type'] = normalized['icmp_access_type'] in ['PING', 'PING_TRACEROUTING']

# Handle special case for server_group_ids
if "server_groups" in app:
normalized["server_group_ids"] = [group['id'] for group in app["server_groups"]]

# Normalize other attributes as needed
# Add other normalization logic here

return normalized


# Function to handle App Connector and Service Edge Group validations
def validate_latitude(val):
try:
v = float(val)
if v < -90 or v > 90:
return (None, ["latitude must be between -90 and 90"])
except ValueError:
return (None, ["latitude value should be a valid float number"])
return (None, None)


def validate_longitude(val):
try:
v = float(val)
if v < -180 or v > 180:
return (None, ["longitude must be between -180 and 180"])
except ValueError:
return (None, ["longitude value should be a valid float number"])
return (None, None)


def diff_suppress_func_coordinate(old, new):
try:
o = round(float(old) * 1000000) / 1000000
n = round(float(new) * 1000000) / 1000000
return o == n
except ValueError:
return False


def validate_tcp_quick_ack(
tcp_quick_ack_app, tcp_quick_ack_assistant, tcp_quick_ack_read_assistant
):
if (
tcp_quick_ack_app != tcp_quick_ack_assistant
or tcp_quick_ack_app != tcp_quick_ack_read_assistant
or tcp_quick_ack_assistant != tcp_quick_ack_read_assistant
):
return "the values of tcpQuickAck related flags need to be consistent"
return None

# Function to handle all policy type conditions and normalize upstream computed attributes
def map_conditions(conditions_obj):
result = []

Expand Down
14 changes: 0 additions & 14 deletions plugins/module_utils/zpa_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,6 @@
"PREVIEW",
}


def deleteNone(_dict):
"""Delete None values recursively from all of the dictionaries, tuples, lists, sets"""
if isinstance(_dict, dict):
for key, value in list(_dict.items()):
if isinstance(value, (list, dict, tuple, set)):
_dict[key] = deleteNone(value)
elif value is None or key is None:
del _dict[key]
elif isinstance(_dict, (list, set, tuple)):
_dict = type(_dict)(deleteNone(item) for item in _dict if item is not None)
return _dict


def to_zscaler_sdk_cls(pkg_name, cls_name):
sdk_name = "zscaler"

Expand Down
48 changes: 7 additions & 41 deletions plugins/modules/zpa_app_connector_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,53 +180,19 @@

from ansible.module_utils._text import to_native
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.zscaler.zpacloud.plugins.module_utils.utils import (
validate_latitude,
validate_longitude,
diff_suppress_func_coordinate,
validate_tcp_quick_ack,
deleteNone,
)
from ansible_collections.zscaler.zpacloud.plugins.module_utils.zpa_client import (
deleteNone,
ZPAClientHelper,
)


def validate_latitude(val):
try:
v = float(val)
if v < -90 or v > 90:
return (None, ["latitude must be between -90 and 90"])
except ValueError:
return (None, ["latitude value should be a valid float number"])
return (None, None)


def validate_longitude(val):
try:
v = float(val)
if v < -180 or v > 180:
return (None, ["longitude must be between -180 and 180"])
except ValueError:
return (None, ["longitude value should be a valid float number"])
return (None, None)


def diff_suppress_func_coordinate(old, new):
try:
o = round(float(old) * 1000000) / 1000000
n = round(float(new) * 1000000) / 1000000
return o == n
except ValueError:
return False


def validate_tcp_quick_ack(
tcp_quick_ack_app, tcp_quick_ack_assistant, tcp_quick_ack_read_assistant
):
if (
tcp_quick_ack_app != tcp_quick_ack_assistant
or tcp_quick_ack_app != tcp_quick_ack_read_assistant
or tcp_quick_ack_assistant != tcp_quick_ack_read_assistant
):
return "the values of tcpQuickAck related flags need to be consistent"
return None


def core(module):
state = module.params.get("state", None)
client = ZPAClientHelper(module)
Expand Down
Loading

0 comments on commit 99e8a30

Please sign in to comment.