2929import org .apache .cloudstack .tosca .model .ToscaTypeDefinition ;
3030import org .apache .commons .collections .CollectionUtils ;
3131import org .apache .commons .collections .MapUtils ;
32+ import org .apache .logging .log4j .LogManager ;
33+ import org .apache .logging .log4j .Logger ;
3234
3335import javax .inject .Inject ;
3436import java .util .HashMap ;
3941import java .util .stream .Collectors ;
4042
4143public class ToscaServiceTemplateParser {
44+ private final Logger logger = LogManager .getLogger (ToscaServiceTemplateParser .class );
45+
46+ private final ToscaFieldParser toscaFieldParser ;
47+
4248 @ Inject
43- private ToscaFieldParser toscaFieldParser ;
49+ public ToscaServiceTemplateParser (ToscaFieldParser toscaFieldParser ) {
50+ this .toscaFieldParser = toscaFieldParser ;
51+ }
4452
4553 public ToscaServiceTemplate parseServiceTemplate (String content , Map <String , ToscaNodeType > toscaProfile , Account caller ) {
4654 Map <String , Object > rawToscaTemplate = ToscaYamlHelper .asMap (ToscaYamlHelper .loadYaml (content ));
@@ -62,6 +70,28 @@ public ToscaServiceTemplate parseServiceTemplate(String content, Map<String, Tos
6270 return new ToscaServiceTemplate ();
6371 }
6472
73+ /**
74+ * Checks whether all the YAML keys present in the root and service_template levels of
75+ * TOSCA service templates are known and whether all the required ones were provided.
76+ * @param template The TOSCA service template to be validated.
77+ * @param context The service template parsing context ({@link ToscaServiceTemplateParsingContext}) for error handling purposes.
78+ * @throws InvalidParameterValueException When unknown keys are present or required keys are missing.
79+ */
80+ private void checkRootServiceTemplateYamlKeys (Map <String , Object > template , ToscaServiceTemplateParsingContext context ) {
81+ validateKnownToscaKeys (template , Set .of (ToscaConstants .SERVICE_TEMPLATE_TOSCA_VERSION_KEY , ToscaConstants .SERVICE_TEMPLATE_DESCRIPTION_KEY , ToscaConstants .SERVICE_TEMPLATE_SERVICE_TEMPLATE_KEY ), "Root level" , context );
82+ validateRequiredToscaKeys (template , Set .of (ToscaConstants .SERVICE_TEMPLATE_SERVICE_TEMPLATE_KEY ), "Root level" , context );
83+ if (context .hasErrors ()) {
84+ throw new InvalidParameterValueException (context .buildErrorMessages ());
85+ }
86+
87+ Map <String , Object > serviceTemplateSection = ToscaYamlHelper .asMap (template .get (ToscaConstants .SERVICE_TEMPLATE_SERVICE_TEMPLATE_KEY ));
88+ validateKnownToscaKeys (serviceTemplateSection , Set .of (ToscaConstants .SERVICE_TEMPLATE_NODE_TEMPLATES_KEY , ToscaConstants .SERVICE_TEMPLATE_INPUTS_KEY , ToscaConstants .SERVICE_TEMPLATE_SERVICE_TEMPLATE_KEY ), "Service template level" , context );
89+ validateRequiredToscaKeys (serviceTemplateSection , Set .of (ToscaConstants .SERVICE_TEMPLATE_NODE_TEMPLATES_KEY ), "Service template level" , context );
90+ if (context .hasErrors ()) {
91+ throw new InvalidParameterValueException (context .buildErrorMessages ());
92+ }
93+ }
94+
6595 private void checkUnresolvedProperties (Map <String , ToscaNodeTemplate > nodeTemplates , String function , ToscaServiceTemplateParsingContext context ) {
6696 Map <String , Set <ToscaProperty >> unresolvedProperties = "$get_property" .equals (function ) ? context .getUnresolvedByGetProperty () : context .getUnresolvedByGetAttribute ();
6797 for (Map .Entry <String , Set <ToscaProperty >> entry : unresolvedProperties .entrySet ()) {
@@ -129,20 +159,6 @@ private Map<String, Set<ToscaNodeTemplate>> buildGraphDependencies(Map<String, T
129159 return serviceTemplateDependencies ;
130160 }
131161
132- private void checkRootServiceTemplateYamlKeys (Map <String , Object > serviceTemplate , ToscaServiceTemplateParsingContext context ) {
133- validateKnownToscaKeys (serviceTemplate , Set .of (ToscaConstants .SERVICE_TEMPLATE_TOSCA_VERSION_KEY , ToscaConstants .SERVICE_TEMPLATE_DESCRIPTION_KEY , ToscaConstants .SERVICE_TEMPLATE_SERVICE_TEMPLATE_KEY ), "YAML's root level" , context );
134- validateRequiredToscaKeys (serviceTemplate , Set .of (ToscaConstants .SERVICE_TEMPLATE_SERVICE_TEMPLATE_KEY ), "YAML's root level" , context );
135- if (context .hasErrors ()) {
136- throw new InvalidParameterValueException (context .buildErrorMessages ());
137- }
138-
139- validateKnownToscaKeys (serviceTemplate , Set .of (ToscaConstants .SERVICE_TEMPLATE_TOSCA_VERSION_KEY , ToscaConstants .SERVICE_TEMPLATE_DESCRIPTION_KEY , ToscaConstants .SERVICE_TEMPLATE_SERVICE_TEMPLATE_KEY ), "YAML's root level" , context );
140- validateRequiredToscaKeys (serviceTemplate , Set .of (ToscaConstants .SERVICE_TEMPLATE_NODE_TEMPLATES_KEY , ToscaConstants .SERVICE_TEMPLATE_INPUTS_KEY ), "Service template level" , context );
141- if (context .hasErrors ()) {
142- throw new InvalidParameterValueException (context .buildErrorMessages ());
143- }
144- }
145-
146162 private Map <String , ToscaNodeTemplate > parseNodeTemplates (Map <String , Object > nodeTemplates , ToscaServiceTemplateParsingContext context ) {
147163 Map <String , ToscaNodeTemplate > nodeTemplateDefinitions = new HashMap <>();
148164 for (Map .Entry <String , Object > nodeTemplate : nodeTemplates .entrySet ()) {
@@ -317,15 +333,29 @@ private ToscaInputDefinition parseInput(String name, Map<String, Object> body, T
317333 return new ToscaInputDefinition (name , description , type , defaultValue , validation );
318334 }
319335
320- private void validateRequiredToscaKeys (Map <String , Object > content , Set <String > requiredKeys , String templateSection , ToscaServiceTemplateParsingContext context ) {
336+ /**
337+ * Validate whether all the required TOSCA keys are present in {@param content}.
338+ * @param content The YAML content to be validated.
339+ * @param requiredKeys The TOSCA keys that must be present in {@param content}.
340+ * @param templateSection The section of the service template being validated. Only used for building the error message.
341+ * @param context The service template parsing context ({@link ToscaServiceTemplateParsingContext}) to which error messages might be added.
342+ */
343+ protected void validateRequiredToscaKeys (Map <String , Object > content , Set <String > requiredKeys , String templateSection , ToscaServiceTemplateParsingContext context ) {
321344 requiredKeys .stream ()
322345 .filter (key -> !content .containsKey (key ))
323- .forEach (key -> context .addError (String .format ("The key [%s] is required in the [%s] section ." , key , templateSection ), templateSection ));
346+ .forEach (key -> context .addError (String .format ("The key [%s] is required." , key ), templateSection ));
324347 }
325348
326- private void validateKnownToscaKeys (Map <String , Object > content , Set <String > validKeys , String templateSection , ToscaServiceTemplateParsingContext context ) {
349+ /**
350+ * Validate whether all the YAML keys present in {@param content} are known TOSCA keys.
351+ * @param content The YAML content to be validated.
352+ * @param knownToscaKeys The known TOSCA keys that can be present in{@param content} .
353+ * @param templateSection The section of the service template being validated. Only used for building the error message.
354+ * @param context The service template parsing context ({@link ToscaServiceTemplateParsingContext}) to which error messages might be added.
355+ */
356+ protected void validateKnownToscaKeys (Map <String , Object > content , Set <String > knownToscaKeys , String templateSection , ToscaServiceTemplateParsingContext context ) {
327357 content .keySet ().stream ()
328- .filter (key -> !validKeys .contains (key ))
329- .forEach (key -> context .addError (String .format ("Unknown key [%s] in the [%s] section ." , key , templateSection ), templateSection ));
358+ .filter (key -> !knownToscaKeys .contains (key ))
359+ .forEach (key -> context .addError (String .format ("Unknown key [%s]." , key ), templateSection ));
330360 }
331361}
0 commit comments