Пример #1
0
def vrf_assignment():
    render_vrf = render_template()
    to_add_vrf = render_vrf.assign_vrf()
    for vrf in to_add_vrf:
        vrf_conv = json.loads(vrf)
        try:
            vrf_dup = nautobot.ipam.ip_addresses.get(
                device=vrf_conv["dns_name"], interface=vrf_conv["description"])
        except:
            pass
        print(vrf_dup)
        if vrf_dup == None:
            print("Cannot assign vrf to " + vrf_conv["dns_name"] + " with interface " + \
                  vrf_conv["description"])
        elif vrf_dup.vrf == None and vrf_dup != None:
            if vrf_conv["address"] in str(vrf_dup):
                address_ = str(vrf_dup)
                try:
                    my_vrf = nautobot.ipam.ip_addresses.get(address=address_)
                    vrf_conv["address"] = address_
                    vrf_conv["dns_name"] = " "
                    vrf_conv["description"] = " "
                    print(vrf_conv)
                    add_vrf = my_vrf.update(vrf_conv)
                except pynautobot.RequestError as e:
                    print(e.error)
                    pass
        else:
            print("Duplicated vrf " + vrf_conv["dns_name"])
    print("Done")
Пример #2
0
def connect_cables():
    my_conn = nautobot.dcim.cables
    render_conn = render_template()
    to_add_conn = render_conn.add_connection()
    for conn in to_add_conn:
        conn_conv = json.loads(conn)
        source = nautobot.dcim.interfaces.get(
            name=conn_conv["termination_a_id"][0],
            device=conn_conv["termination_a_id"][1])
        target = nautobot.dcim.interfaces.get(
            name=conn_conv["termination_b_id"][0],
            device=conn_conv["termination_b_id"][1])
        if source != None:
            conn_conv["termination_a_id"] = source.id
        if target != None:
            conn_conv["termination_b_id"] = target.id
        try:
            print(conn_conv)
            add_conn = my_conn.create(conn_conv)
            print("Done with " + str(source) + " " + str(target))
        except pynautobot.RequestError as e:
            error_log.write("{0} {1}\n{2}\n".format(source, target,
                                                    str(e.error)))
            print(source, target)
            print(e.error)
            pass
Пример #3
0
def region():
    my_region = nautobot.dcim.regions
    render_region = render_template()
    to_add_region = render_region.region()
    for regions in to_add_region:
        add_region = my_region.create(regions)
    print("Done")
Пример #4
0
def ipadd_be():
    my_ipadd = nautobot.ipam.ip_addresses
    render_ipadd = render_template()
    to_add_ipadd = render_ipadd.ipadd_be()
    for ipadd in to_add_ipadd:
        ipadd_conv = json.loads(ipadd)
        #print(ipadd_conv)
        bundle = nautobot.dcim.interfaces.get(
            name=ipadd_conv["assigned_object"]["name"],
            device=ipadd_conv["assigned_object"]["device"]["name"])
        print(bundle)
        try:
            dup_ip = my_ipadd.get(assigned_object_id=bundle.id,
                                  address=ipadd_conv["address"])
        except:
            print("No address or no interface defined!")
        if bundle != None and dup_ip == None:
            print(bundle.id)
            ipadd_conv['assigned_object']['id'] = bundle.id
            ipadd_conv['assigned_object_id'] = bundle.id
            print(ipadd_conv)
            # try:
            add_ipadd = my_ipadd.create(ipadd_conv)
        # except pynautobot.RequestError as e:
        #     print(e.error)
        #     pass
        elif bundle == None:
            print("No defined interface bundle")
        elif dup_ip != None:
            print("Duplicate IP " + ipadd_conv['address'])
    print("Done")
Пример #5
0
def roles():
    my_roles = nautobot.dcim.device_roles
    render_roles = render_template()
    to_add_roles = render_roles.roles()
    for roles in to_add_roles:
        print(roles)
        roles_conv = json.loads(roles)
        add_roles = my_roles.create(json.loads(roles))
    print("Done")
Пример #6
0
def update_custom():
    my_custom = nautobot.dcim.devices.get(
        "33e89bbe-6da2-411e-9fca-7792a66b22bf")
    render_custom = render_template()
    to_add_custom = render_custom.custom_field()
    for fields in to_add_custom:
        try:
            print(fields)
            add_custom = my_custom.update(json.loads(fields))
        except:
            print('Cannot upload ' + fields + '.')
    print("Done")
Пример #7
0
def loopback():
    my_interface = nautobot.dcim.interfaces
    render_interfaces = render_template()
    to_add_interfaces = render_interfaces.loop_interfaces()
    for interfaces in to_add_interfaces:
        try:
            print(interfaces)
            interfaces_conv = json.loads(interfaces)
            add_interfaces = my_interface.create(interfaces_conv)
        except:
            print('Cannot upload ' + interfaces)
    print("Done")
Пример #8
0
def devices():
    my_devices = nautobot.dcim.devices
    render_devices = render_template()
    to_add_devices = render_devices.devices()
    for devices in to_add_devices:
        try:
            print(devices)
            devices_conv = json.loads(devices)
            add_devices = my_devices.create(devices_conv)
        except pynautobot.RequestError as e:
            print(e.error)
            pass
    print("Done")
Пример #9
0
def bundle_interface():
    my_be = nautobot.dcim.interfaces
    render_be = render_template()
    to_add_be = render_be.be_int()
    for be in to_add_be:
        try:
            print(be)
            be_conv = json.loads(be)
            add_be = my_be.create(be_conv)
        except pynautobot.RequestError as e:
            print(e.error)
            pass
    print("Done")
Пример #10
0
def physical_interface():
    my_phy = nautobot.dcim.interfaces
    render_phy = render_template()
    to_add_phy = render_phy.phy_int()
    for phy in to_add_phy:
        try:
            print(phy)
            phy_conv = json.loads(phy)
            add_phy = my_phy.create(phy_conv)
        except pynautobot.RequestError as e:
            print(e.error)
            pass
    print("Done")
Пример #11
0
def sites():
    my_sites = nautobot.dcim.sites
    render_sites = render_template()
    to_add_sites = render_sites.sites()
    for sites in to_add_sites:
        try:
            print(sites)
            sites_conv = json.loads(sites)
            add_sites = my_sites.create(sites_conv)
        except pynautobot.RequestError as e:
            print(e.error)
            pass
    print("Done")
Пример #12
0
def update_device():
    my_devices = nautobot.dcim.devices.get(
        "33e89bbe-6da2-411e-9fca-7792a66b22bf")
    render_devices = render_template()
    to_add_devices = render_devices.patch_devices()
    for devices in to_add_devices:
        try:
            print(devices)
            add_devices = my_devices.update(json.loads(devices))
        except:
            print('Cannot upload ' + devices +
                  '. Check for duplicates or hostname in wrong format!')
    print("Done")
Пример #13
0
def assign_primary():
    my_primary = nautobot.dcim.devices.get(
        "33e89bbe-6da2-411e-9fca-7792a66b22bf")
    render_primary = render_template()
    to_add_primary = render_primary.patch_devices()
    for pri in to_add_primary:
        try:
            print(pri)
            pri_conv = json.loads(pri)
            add_primary = my_primary.update(pri_conv)
        except pynautobot.RequestError as e:
            print(e.error)
            pass
    print("Done")
Пример #14
0
def ipadd_loop():
    my_ipadd = nautobot.ipam.ip_addresses
    render_ipadd = render_template()
    to_add_ipadd = render_ipadd.ipadd_loopback()

    for ipadd in to_add_ipadd:
        try:
            print(ipadd)
            ipadd_conv = json.loads(ipadd)
            add_ipadd = my_ipadd.create(ipadd_conv)
        except pynautobot.RequestError as e:
            print(e.error)
            pass
    print("Done")
Пример #15
0
def interface_shut():
    my_phy = nautobot.dcim.interfaces
    render_phy = render_template()
    to_add_phy = render_phy.shut_interfaces()
    for phy in to_add_phy:
        try:
            print(phy)
            phy_conv = json.loads(phy)
            #my_phy = nautobot.dcim.interfaces.get(device=phy_conv["device"]["name"],name=phy_conv["name"])
            add_phy = my_phy.create(phy_conv)
            #add_phy = my_phy.update(phy_conv)
        except pynautobot.RequestError as e:
            print(e.error)
            pass
    print("Done")
Пример #16
0
def inventory():
    my_inventory = nautobot.dcim.inventory_items
    render_devices = render_template()
    to_add_inventory = render_devices.inventory()
    for inventory in to_add_inventory:
        inventory_conv = json.loads(inventory)
        device = nautobot.dcim.devices.get(
            name=inventory_conv["device"]["name"])
        if device != None:
            inventory_conv["device"]["id"] = device.id
            print(inventory_conv)
        try:
            add_inventory = my_inventory.create(inventory_conv)
        except pynautobot.RequestError as e:
            print(e.error)
            pass
    print("Done")
Пример #17
0
def vrf():
    my_vrf = nautobot.ipam.vrfs
    render_vrf = render_template()
    to_add_vrf = render_vrf.vrf()
    for vrf in to_add_vrf:
        vrf_conv = json.loads(vrf)
        dup_vrf = nautobot.ipam.vrfs.get(name=vrf_conv["name"])
        if dup_vrf == None:
            try:
                print(vrf)
                add_vrf = my_vrf.create(vrf_conv)
            except pynautobot.RequestError as e:
                print(e.error)
                pass
        else:
            print("Duplicated vrf " + str(dup_vrf))
    print("Done")
Пример #18
0
def vlan():
    my_vlan = nautobot.ipam.vlans
    render_vlan = render_template()
    to_add_vlan = render_vlan.vlan()
    for vlan in to_add_vlan:
        vlan_conv = json.loads(vlan)
        dup_vlan = nautobot.ipam.vlans.get(name=vlan_conv["name"])
        if dup_vlan == None:
            try:
                print(vlan)
                add_vlan = my_vlan.create(vlan_conv)
            except pynautobot.RequestError as e:
                print(e.error)
                pass
        else:
            print("Duplicated vlan " + str(dup_vlan))
    print("Done")
Пример #19
0
def rt():
    my_rt = nautobot.ipam.route_targets
    render_rt = render_template()
    to_add_rt = render_rt.rt()
    for rt in to_add_rt:
        rt_conv = json.loads(rt)
        try:
            dup_rt = nautobot.ipam.route_targets.get(name=rt_conv["name"])
        except:
            continue
        if dup_rt == None:
            try:
                print(rt)
                add_rt = my_rt.create(rt_conv)
            except pynautobot.RequestError as e:
                print(e.error)
                pass
        else:
            print("Duplicated RT " + str(dup_rt))
    print("Done")
Пример #20
0
def assign_rt():
    render_rt = render_template()
    to_add_rt = render_rt.assign_rt()
    for rt in to_add_rt:
        print(rt)
        rt_conv = json.loads(rt)
        try:
            dup_rt = nautobot.ipam.vrfs.get(import_targets=rt_conv["import_targets"],export_targets=rt_conv\
                ["export_targets"])
        except:
            dup_rt = None
            pass
        if dup_rt == None:
            my_rt = nautobot.ipam.vrfs.get(name=rt_conv["name"])
            if my_rt != None:
                rt_ex_list = []
                rt_imp_list = []
                for rt_ex in rt_conv["export_targets"]:
                    print(rt_ex)
                    rt_export = nautobot.ipam.route_targets.get(name=rt_ex)
                    rt_ex_id = rt_export.id
                    rt_ex_list.append(rt_ex_id)
                for rt_imp in rt_conv["import_targets"]:
                    print(rt_imp)
                    rt_import = nautobot.ipam.route_targets.get(name=rt_imp)
                    rt_imp_id = rt_import.id
                    rt_imp_list.append(rt_imp_id)
                rt_conv["export_targets"] = rt_ex_list
                rt_conv["import_targets"] = rt_imp_list
                print(rt_conv)
                # try:
                add_rt = my_rt.update(rt_conv)
                print("Done for " + rt_conv["name"])
            # except pynautobot.RequestError as e:
            #     print(e.error)
            #     pass
            else:
                continue
        else:
            print("Duplicated RT " + str(dup_rt))
    print("Done")
Пример #21
0
def assign_vlan():
    render_vlan = render_template()
    to_add_vlan = render_vlan.assign_vlan()
    for vlan in to_add_vlan:
        print(vlan)
        vlan_conv = json.loads(vlan)
        try:
            vlan_dup = nautobot.dcim.interfaces.get(device=vlan_conv["device"]["name"], interface=vlan_conv["name"],\
                                                    vlan=vlan_conv["untagged_vlan"])
        except:
            pass
        print(vlan_dup)
        # if vlan_dup == None:
        #     print("Cannot assign vlan to " + vlan_conv["device"]["name"] + " with interface " + \
        #           vrf_conv["name"])
        if vlan_dup == None:
            my_vlan = nautobot.ipam.vlans.get(name=vlan_conv["untagged_vlan"])
            my_vlan_int = nautobot.dcim.interfaces.get(name=vlan_conv["name"],\
                                                      device=vlan_conv["device"]["name"])
            vlan_conv["untagged_vlan"] = my_vlan.id
            print(vlan_conv)
            if my_vlan_int != None:
                try:
                    add_vlan = my_vlan_int.update(vlan_conv)
                except pynautobot.RequestError as e:
                    error_log.write("{0} {1}\n{2}\n".format(
                        vlan_conv["name"], vlan_conv["device"]["name"],
                        str(e.error)))
                    print(e.error)
                    pass
            else:
                error_log.write("Hostname " + vlan_conv["device"]["name"] + " and/or interface " + \
                      vlan_conv["name"] + " is not yet defined.\n")
                print("Hostname " + vlan_conv["device"]["name"] + " and/or interface " + \
                      vlan_conv["name"] + " is not yet defined.")
        else:
            error_log.write("Duplicated vlan of " + vlan_conv["device"]["name"] + " " + vlan_conv["name"] + " " + \
                            vlan_conv["untagged_vlan"] + "\n")
            print("Duplicated vlan of " + vlan_conv["device"]["name"] + " " +
                  vlan_conv["name"] + " " + vlan_conv["untagged_vlan"])
    print("Done")
Пример #22
0
def main(config):

    ### MODULE IMPORTS

    import os, string
    import xml.etree.ElementTree as ET

    from os import path
    from string import Template
    from collections import ChainMap

    from modules.helpers import read_json
    from modules.helpers import log_error
    from modules.helpers import log_ok
    from modules.helpers import go_to_folder
    from modules.helpers import create_file
    from modules.helpers import read_template
    from modules.helpers import obj_forbidden
    from modules.helpers import write_line
    from modules.helpers import get_stored_value
    from modules.parse_values import main as parse_values
    from modules.parse_classes import main as parse_classes

    from modules.do_operation import do_operation
    from modules.render_template import render_template

    log_ok("Initializing...")

    ### PATH VALUES

    MODULE_PATH = os.path.join(os.path.dirname(__file__))
    HOME_DIR = os.getcwd()

    ### PARSE JSON CONFIG FILE

    try:
        config = read_json(config)
    except Exception as e:
        return log_error("Invalid config file.")
    finally:
        log_ok("Valid config file.")

    ### STORE ALL GLOBAL VALUES

    try:
        classes = read_json("classes.json")

        stored_values = parse_values(classes["values"])
        stored_classes = parse_classes(classes["classes"])
    except Exception as e:
        return log_error(f"Invalid classes file or error: {e}")

    ### SPACING VALUES

    TEMPLATE_LINE = 5
    TAB_SPACE = 3
    NL = "\n"

    ### ROOT CONFIG VARIABLES

    try:
        MODS_DIR = config["target_folder"]
        OUTPUT_DIR = config["output_folder"]
        CONFIG_MODS = config["main"]
    except Exception as e:
        return log_error((f"Property: {str(e)} missing from main config."))

    GAME_MODS_DIR = (MODS_DIR + "/")

    try:
        if not os.path.exists(OUTPUT_DIR):
            raise
    except Exception:
        return log_error("Output directory does not exist.")
    finally:
        log_ok("Valid output directory.")

    ### MOD CONFIG VARIABLES

    for mod in CONFIG_MODS:
        try:
            mod_folder = mod["folder"]
            mod_defs = mod["defs"]
        except Exception as e:
            return log_error((f"Property: {str(e)} missing from mod config."))
        try:
            folder_name = (mod["label"] if ("label" in mod) else mod_folder)
            current_def_path = (GAME_MODS_DIR + mod_folder + "/Defs/")
        except Exception as e:
            return log_error(e)

        ### DEF CONFIG VARIABLES

        for mod_def in mod_defs:
            print("--------------")
            try:
                def_folder = mod_def["folder"]
                def_files = mod_def["files"]
            except Exception as e:
                return log_error(
                    (f"Property: {str(e)} missing from def config."))
            try:
                def_path = ("/" +
                            mod_def["path"]) if ("path" in mod_def) else "Defs"
                def_defType = mod_def["defType"] if (
                    "defType" in mod_def) else "ThingDef"
                mod_def_path = (current_def_path + def_folder + "/")
                def_file_exported = {}
            except Exception as e:
                return log_error(e)

            ### CREATE BASE FOLDER FOR MOD

            go_to_folder(OUTPUT_DIR, folder_name, HOME_DIR)
            log_ok(f"Mod folder {folder_name} created.")

            ### FILE CONFIG VARIABLES

            for def_file in def_files:
                try:
                    def_file_defName = def_file["defName"]
                    def_defFilename = def_file["filename"] if (
                        "filename" in def_file) else None
                    def_file_properties = def_file["properties"]
                except Exception as e:
                    return log_error(
                        (f"Property: {str(e)} missing from file config."))

                ### PARSE CLASS PROPERTIES

                try:
                    def_file_Class = def_file["Classes"] if (
                        "Classes" in def_file) else None

                    if not (def_file_Class is None):
                        cache_properties = []
                        for c_class in def_file_Class:
                            if (c_class in stored_classes):
                                def_file = (dict(
                                    ChainMap(stored_classes[c_class],
                                             def_file)))
                                matching_class = stored_classes[c_class]
                                if ("properties" in matching_class):
                                    for vp in matching_class["properties"]:
                                        cache_properties.append(vp)
                                    for vp in def_file_properties:
                                        cache_properties.append(vp)
                                    def_file_properties = cache_properties
                        def_file.pop("Classes", None)
                except Exception as e:
                    return log_error(e)
                print("-----------------")

                ### PARSE XML FILE

                try:
                    xml_file = (mod_def_path + def_file_defName + ".xml")
                    if not os.path.isfile(xml_file):
                        raise
                except Exception as e:
                    return log_error(f"File {xml_file} does not exist!")
                try:
                    tree = ET.parse(xml_file)
                    root = tree.getroot()
                except Exception as e:
                    return log_error(f"Failed to parse XML file. ({e}).")

                log_ok(f"Read {def_file_defName}.xml.", 2)

                def_file_exported[def_file_defName] = []
                exported_properties = {}

                ### CREATE DEF SUB-FOLDER

                go_to_folder(os.path.join(OUTPUT_DIR, folder_name), def_folder,
                             HOME_DIR)

                ### ITERATE THROUGH OBJECTS

                for object_def in root.iter(def_defType):
                    try:
                        obj_defName = object_def.find("defName").text if (
                            object_def.find("defName")
                            is not None) else object_def.get("Name")
                    except Exception as e:
                        return log_error(e)

                    ### CHECK IF OBJECT IS INCLUDED/EXCLUDED

                    if obj_forbidden(def_file, obj_defName):
                        continue

                    ### OPTIONAL LABEL/DESC VARIABLES

                    try:
                        obj_label = object_def.find("label").text if (
                            object_def.find("label") is not None) else ""
                        obj_defType = def_file["defType"] if (
                            "defType" in def_file) else def_defType
                        exported_properties[obj_defName] = {
                            "label": obj_label,
                            "values": []
                        }
                    except Exception as e:
                        return log_error(e)

                    ### LOOP THROUGH OBJECT PROPERTIES

                    for def_prop in def_file_properties:
                        try:
                            def_prop_tree = def_prop["tree"]
                            def_prop_property = def_prop["property"]
                            def_prop_procedure = def_prop["procedure"] if (
                                "procedure" in def_prop) else "Replace"
                        except Exception as e:
                            return log_error((
                                f"Property: {str(e)} missing from property config."
                            ))
                        try:
                            prop_path = "/".join(def_prop_tree)
                        except Exception as e:
                            return log_error(e)

                        ### PROPERTY FILTER FOR INCLUDED/EXCLUDED OBJECTS

                        for target_prop in object_def.findall(prop_path):
                            if obj_forbidden(def_prop, obj_defName):
                                continue

                            ftp = 0
                            final_prop_path = ""

                            if (def_prop_procedure == "Replace"):

                                final_prop_path = (
                                    f"{prop_path}/{def_prop_property}")

                                for final_prop in target_prop.iter(
                                        def_prop_property):
                                    fpt = final_prop.text

                                    ### PERFORM ARITHMETIC OPERATION OR ASSIGN VALUE

                                    try:
                                        if ("operation" in def_prop):
                                            normalized_values = get_stored_value(
                                                def_prop["operation"],
                                                stored_values)

                                            fpt = float(
                                                fpt) if '.' in fpt else int(
                                                    fpt)
                                            fpt = do_operation(
                                                fpt, normalized_values)
                                            fpt = round(
                                                fpt, normalized_values[3] if
                                                (len(normalized_values)
                                                 == 4) else 2)
                                        elif ("value" in def_prop):
                                            fpt = get_stored_value(
                                                def_prop["value"],
                                                stored_values)[0]
                                        else:
                                            raise
                                    except Exception as e:
                                        return log_error(
                                            f"Property '{obj_defName}' has no valid value or operation: {e}."
                                        )

                            if (def_prop_procedure == "Add"):

                                final_prop_path = (f"{prop_path}")

                                for proc_key, proc_attr in def_prop_property.items(
                                ):
                                    def_prop_property[
                                        proc_key] = get_stored_value(
                                            proc_attr, stored_values)[0]

                            ### APPEND NEW DICTIONARY INTO LIST

                            this_export = {
                                "defType":
                                obj_defType,
                                "defPath":
                                def_path,
                                "defName":
                                obj_defName,
                                "propPath":
                                final_prop_path,
                                "mainProp":
                                def_prop_property,
                                "finalValue":
                                fpt,
                                "defProcedure":
                                def_prop_procedure,
                                "finalFilename":
                                def_defFilename,
                                "taskDesc":
                                def_prop["desc"] if
                                ("desc" in def_prop) else None
                            }
                            exported_properties[obj_defName]["values"].append(
                                this_export)
                log_ok("Properties processed.", 3)

                ### APPEND DEF LIST INTO MOD PROPERTIES

                def_file_exported[def_file_defName].append(exported_properties)

            ### LOOP THROUGH MOD PROPERTIES

            log_ok(f"Creating patch files...", 1)

            for attr, sub_mod_def in def_file_exported.items():

                log_ok(f"/{def_folder}:", 2)

                ### CREATE OUTPUT FILE AND READ MAIN TEMPLATE

                output_filename = attr

                for def_key in def_files:
                    if (("filename" in def_key)
                            and (def_key["defName"] == attr)):
                        output_filename = def_key["filename"]

                try:
                    output_file = create_file(
                        os.path.join(OUTPUT_DIR, folder_name, def_folder),
                        (output_filename + ".xml"))
                    tpl_template = read_template(HOME_DIR, "main")

                    sub_def_file = {}
                except Exception as e:
                    return log_error(e)

                ### LOOP THROUGH TEMPLATE LINES UNTIL MIDDLE SECTION

                for line_count, main_template_line in enumerate(tpl_template):
                    if (line_count == TEMPLATE_LINE):

                        ### MOD HEADER COMMENT

                        try:
                            mod_header_dict = {
                                "label":
                                ("CONTENT: " + (mod["label"] if "label" in mod
                                                else mod_folder)),
                                "desc":
                                mod["desc"] if ("desc" in mod) else "",
                            }
                            for line in read_template(HOME_DIR, "header_long"):
                                output_file.write(
                                    write_line(
                                        render_template(
                                            "header_long", Template(line),
                                            mod_header_dict), 1))
                        except Exception as e:
                            return log_error(e)

                        ### DEF HEADER COMMENT

                        try:
                            sub_def_file = {}
                            for s in def_files:
                                if (s["defName"] == attr): sub_def_file = s

                            if (len(sub_def_file) > 0):
                                def_header_dict = {
                                    "label":
                                    ("PATCH: " +
                                     ((sub_def_file["label"])
                                      if "label" in sub_def_file else "")),
                                    "desc":
                                    sub_def_file["desc"]
                                    if "desc" in sub_def_file else "",
                                }
                                if ("label" in sub_def_file):
                                    for line in read_template(
                                            HOME_DIR, "header_mid"):
                                        output_file.write(
                                            write_line(
                                                render_template(
                                                    "header_long",
                                                    Template(line),
                                                    def_header_dict),
                                                (TAB_SPACE - 1)))
                        except Exception as e:
                            return log_error(e)

                        ### LOOP THROUGH DEF OBJECTS

                        for prop in sub_mod_def:
                            for i, sp_def_file in prop.items():

                                ### OBJECT LABEL COMMENT

                                if (len(sp_def_file["values"]) > 0):
                                    try:
                                        labelHeader = sp_def_file["label"] if (
                                            "label" in sp_def_file) else i

                                        for line in read_template(
                                                HOME_DIR, "header"):
                                            output_file.write(
                                                write_line(
                                                    render_template(
                                                        "header",
                                                        Template(line),
                                                        {"label": labelHeader
                                                         }), TAB_SPACE))
                                    except Exception as e:
                                        return log_error(e)

                                    for exp_values in sp_def_file["values"]:

                                        ### TASK DESCRIPTION COMMMENT

                                        if (exp_values["taskDesc"]
                                                is not None):
                                            try:
                                                for line in read_template(
                                                        HOME_DIR, "header"):
                                                    output_file.write(
                                                        write_line(
                                                            render_template(
                                                                "header",
                                                                Template(line),
                                                                {
                                                                    "label":
                                                                    ("CHANGE: "
                                                                     +
                                                                     exp_values[
                                                                         "taskDesc"]
                                                                     )
                                                                }), TAB_SPACE,
                                                            0))
                                                output_file.write(NL)
                                            except Exception as e:
                                                return log_error(e)

                                        ### WRITE REPLACEMENT XPATH OPERATION

                                        valuesList = ""
                                        mainProp = exp_values["mainProp"]
                                        finalValue = exp_values["finalValue"]

                                        if (exp_values["defProcedure"] ==
                                                "Replace"):
                                            valuesList = (
                                                valuesList + get_proc_line(
                                                    mainProp, finalValue))

                                        if (exp_values["defProcedure"] == "Add"
                                            ):
                                            for exp_key, exp_attr in mainProp.items(
                                            ):
                                                valuesList = (
                                                    valuesList + get_proc_line(
                                                        exp_key, exp_attr))

                                        exp_values["valuesList"] = valuesList

                                        try:
                                            for line in read_template(
                                                    HOME_DIR, "procedure"):
                                                output_file.write(
                                                    write_line(
                                                        render_template(
                                                            "main",
                                                            Template(line),
                                                            exp_values),
                                                        TAB_SPACE, 0))
                                        except Exception as e:
                                            return log_error(e)

                                        output_file.write(NL * 2)
                    else:
                        output_file.write(main_template_line)
                log_ok(f"Created {attr}.", 3)

                ### CLOSES FILES

                output_file.close()
                tpl_template.close()

    print()
    log_ok("All tasks executed successfully!")
    True

    ### 👍😎