@@ -456,6 +456,7 @@ def __init__(self, module):
456456 super ().__init__ (module )
457457 self .module_schema = self .get_workflow_elements_schema ()
458458 self .module_name = "template_workflow_manager"
459+ self .project_description_map = None
459460
460461 def validate_input (self ):
461462 """
@@ -760,6 +761,48 @@ def transform_containing_templates(self, template_details):
760761
761762 return final_containing_templates
762763
764+ def transform_template_params (self , template_details ):
765+ """
766+ Transforms template parameters from camelCase API response format to snake_case
767+ format compatible with the template_workflow_manager module.
768+
769+ Uses the base class camel_to_snake_case() for recursive conversion of all
770+ fields including nested range and selection objects.
771+
772+ Args:
773+ template_details (dict): A dictionary containing template-specific information.
774+
775+ Returns:
776+ list: A list of dictionaries containing transformed template parameter information.
777+ Each dictionary may contain keys such as parameter_name, data_type,
778+ default_value, description, range, selection, etc.
779+ """
780+
781+ self .log (
782+ "Starting template params transformation for template: {0}" .format (
783+ template_details .get ("name" , "Unknown" )
784+ ),
785+ "DEBUG"
786+ )
787+
788+ template_params = template_details .get ("templateParams" , [])
789+ if not template_params :
790+ self .log ("No template params found in template details" , "DEBUG" )
791+ return template_params
792+
793+ self .log ("Processing {0} template param(s)" .format (len (template_params )), "DEBUG" )
794+
795+ final_template_params = self .camel_to_snake_case (template_params )
796+
797+ self .log (
798+ "Completed template params transformation. Transformed {0} param(s)" .format (
799+ len (final_template_params )
800+ ),
801+ "DEBUG"
802+ )
803+
804+ return final_template_params
805+
763806 def containing_templates_temp_spec (self ):
764807 """
765808 Constructs a temporary specification for containing templates, defining the structure and types of attributes
@@ -817,6 +860,11 @@ def templates_temp_spec(self):
817860 "template_name" : {"type" : "str" , "source_key" : "name" },
818861 "template_description" : {"type" : "str" , "source_key" : "description" },
819862 "project_name" : {"type" : "str" , "source_key" : "projectName" },
863+ "project_description" : {
864+ "type" : "str" ,
865+ "special_handling" : True ,
866+ "transform" : self .transform_project_description ,
867+ },
820868 "author" : {"type" : "str" },
821869 "language" : {"type" : "str" },
822870 "composite" : {"type" : "bool" },
@@ -841,6 +889,12 @@ def templates_temp_spec(self):
841889 "special_handling" : True ,
842890 "transform" : self .transform_template_content ,
843891 },
892+ "template_params" : {
893+ "type" : "list" ,
894+ "element" : "dict" ,
895+ "special_handling" : True ,
896+ "transform" : self .transform_template_params ,
897+ },
844898 "template_tag" : {
845899 "type" : "list" ,
846900 "element" : "dict" ,
@@ -851,6 +905,80 @@ def templates_temp_spec(self):
851905 )
852906 return template_details
853907
908+ def initialize_project_description_map (self , project_details = None ):
909+ """
910+ Initializes the project_description_map by building a mapping of project names
911+ to their descriptions. If project_details is not provided, fetches project
912+ details from Catalyst Center using get_template_projects_details.
913+
914+ Args:
915+ project_details (list, optional): A list of project dictionaries from the API.
916+ If None, project details will be fetched from Catalyst Center.
917+ """
918+
919+ if project_details is None :
920+ self .log (
921+ "Fetching project details from Catalyst Center for project_description_map" ,
922+ "DEBUG"
923+ )
924+ network_element = self .module_schema ["network_elements" ]["projects" ]
925+ self .get_template_projects_details (
926+ network_element , {"component_specific_filters" : None }
927+ )
928+ return
929+
930+ self .project_description_map = {
931+ p .get ("name" ): p .get ("description" )
932+ for p in (project_details or [])
933+ if p .get ("description" )
934+ }
935+ self .log (
936+ "project_description_map initialized with {0} entries" .format (
937+ len (self .project_description_map )
938+ ),
939+ "DEBUG"
940+ )
941+
942+ def transform_project_description (self , template_details ):
943+ """
944+ Retrieves the project description for a template by looking up the project name
945+ in a cached project description map. Lazily initializes the map by fetching
946+ project details from Catalyst Center if not already populated.
947+
948+ Args:
949+ template_details (dict): A dictionary containing template-specific information
950+ including 'projectName'.
951+
952+ Returns:
953+ str or None: The project description if found, otherwise None.
954+ """
955+
956+ self .log (
957+ "Starting project description lookup for template: {0}" .format (
958+ template_details .get ("name" , "Unknown" )
959+ ),
960+ "DEBUG"
961+ )
962+
963+ if self .project_description_map is None :
964+ self .log (
965+ "project_description_map not initialized, triggering lazy initialization" ,
966+ "DEBUG"
967+ )
968+ self .initialize_project_description_map ()
969+
970+ project_name = template_details .get ("projectName" )
971+ project_description = self .project_description_map .get (project_name )
972+
973+ self .log (
974+ "Completed project description lookup for project '{0}': {1}" .format (
975+ project_name , project_description if project_description else "No description found"
976+ ),
977+ "DEBUG"
978+ )
979+
980+ return project_description
981+
854982 def get_template_projects_details (self , network_element , filters ):
855983 """
856984 Retrieves template project details from Catalyst Center with pagination support.
@@ -959,6 +1087,9 @@ def get_template_projects_details(self, network_element, filters):
9591087 else :
9601088 self .log ("No projects found in Catalyst Center" , "DEBUG" )
9611089
1090+ # Cache project descriptions for use by transform_project_description
1091+ self .initialize_project_description_map (final_template_projects )
1092+
9621093 # Transform using temp spec
9631094 self .log (
9641095 "Transforming {0} project(s) using projects temp spec" .format (
0 commit comments