Skip to content

Validation clauses inconsistencies with TOSCA 2.0 #150

@bernardodemarco

Description

@bernardodemarco

Puccini struggles to parse validation clauses (see TOSCA 2.0 - 9.11. Validation Clause section) when using the TOSCA 2.0 version. With the v0.22.7 Puccini's version:

puccini-tosca version
➜  puccini-tosca version
version=v0.22.7
revision=d425473afe561d1f256e7dc2bdcfa8e0a6265900
timestamp=2025-07-06 14:39:17 CDT
arch=amd64
os=linux
compiler=gc
compiler-version=go1.24.4

Using the following service template, which was derived from an example of the TOSCA's specification (see source):

Service template with validation clauses
tosca_definitions_version: tosca_2_0

node_types:
  Scalable:
    properties:
      minimum-instances:
        type: integer
        validation: { $greater_or_equal: [ $value,  0 ] } 
      maximum-instances:
        type: integer
        validation: 
          $greater_or_equal:
          - $value
          - $get_property: [ SELF, minimum-instances ]
      default-instances:
        type: integer
        validation:
          $and:
          - $greater_or_equal: 
            - $value
            - $get_property: [ SELF, minimum-instances ]
          - $less_or_equal: 
            - $value
            - $get_property: [ SELF, maximum-instances ]
        required: false

service_template:
  node_templates:
    scalable-virtual-machine-group:
      type: Scalable
      properties:
        minimum-instances: 2
        maximum-instances: 6
        default-instances: 2

When trying to compile it, Puccini complains about the validation clauses declared under the properties of the node type:

puccini-tosca compile ./scalable.yaml
➜  puccini-tosca compile scalable.yaml                                                     
PROBLEMS (3)
  file:///home/bernardodemarco/code/puccini-example/scalable.yaml
    @17,9 node_types["Scalable"].properties["default-instances"].validation: unsupported keyname
    @11,9 node_types["Scalable"].properties["maximum-instances"].validation: unsupported keyname
    @8,9 node_types["Scalable"].properties["minimum-instances"].validation: unsupported keyname
puccini-tosca compile --coerce ./scalable.yaml
➜  puccini-tosca compile --coerce scalable.yaml
PROBLEMS (3)
  file:///home/bernardodemarco/code/puccini-example/scalable.yaml
    @17,9 node_types["Scalable"].properties["default-instances"].validation: unsupported keyname
    @11,9 node_types["Scalable"].properties["maximum-instances"].validation: unsupported keyname
    @8,9 node_types["Scalable"].properties["minimum-instances"].validation: unsupported keyname
puccini-tosca validate ./scalable.yaml
➜  puccini-tosca validate scalable.yaml        
PROBLEMS (3)
  file:///home/bernardodemarco/code/puccini-example/scalable.yaml
    @17,9 node_types["Scalable"].properties["default-instances"].validation: unsupported keyname
    @11,9 node_types["Scalable"].properties["maximum-instances"].validation: unsupported keyname
    @8,9 node_types["Scalable"].properties["minimum-instances"].validation: unsupported keyname

When removing the tosca_definitions_version YAML key from the service template, no error is returned:

puccini-tosca compile ./scalable.yaml
➜  puccini-tosca compile ./scalable.yaml                                   
# no error
puccini-tosca validate ./scalable.yaml
➜  puccini-tosca validate ./scalable.yaml                                   
# no error

However, after the removal, other aspects of the TOSCA language are affected. For example, Puccini does not validate the properties of node templates against their respective type definitions:

Service template containing node templates with invalid properties and properties with invalid values
node_types:
  Scalable:
    properties:
      minimum-instances:
        type: integer
        validation: { $greater_or_equal: [ $value,  0 ] } 
      maximum-instances:
        type: integer
        validation: 
          $greater_or_equal:
          - $value
          - $get_property: [ SELF, minimum-instances ]
      default-instances:
        type: integer
        validation:
          $and:
          - $greater_or_equal: 
            - $value
            - $get_property: [ SELF, minimum-instances ]
          - $less_or_equal: 
            - $value
            - $get_property: [ SELF, maximum-instances ]
        required: false

service_template:
  node_templates:
    scalable-virtual-machine-group:
      type: Scalable
      properties:
        # invalid property value
        maximum-instances: djkfndkjf
        default-instances: 2
        # invalid property
        djkfndlkjfnd: dldfndjkfndsk
puccini-tosca compile ./scalable.yaml
➜  puccini-tosca compile ./scalable.yaml                                   
# no error
puccini-tosca validate ./scalable.yaml
➜  puccini-tosca validate ./scalable.yaml                                   
# no error

The inconsistencies when parsing validation clauses are not strictly related with properties definitions. Below, there is a simple service template example, which attempts to validate an input field:

Service template attempting to validate an input field
tosca_definitions_version: tosca_2_0

node_types:
  Scalable:
    properties:
      scalable-group-name:
        type: string
        required: true

service_template:
  inputs:
    scalable-group-name-input:
      type: string
      required: true
      validation: { $greater_or_equal: [ { $length: [ $value ] }, 3 ] }
  node_templates:
    scalable-virtual-machine-group:
      type: Scalable
      properties:
        scalable-group-name: { $get_input: [ scalable-group-name-input ] }

When compiling or validating it:

puccini-tosca compile --input scalable-group-name-input="Scalable Group" ./scalable.yaml
➜  puccini-tosca compile --input scalable-group-name-input="Scalable Group" ./scalable.yaml 
PROBLEMS (1)
  file:///home/bernardodemarco/code/puccini-example/scalable.yaml
    @15,7 service_template.inputs["scalable-group-name-input"].validation: unsupported keyname                         
puccini-tosca compile --coerce --input scalable-group-name-input="Scalable Group" ./scalable.yaml
➜  puccini-tosca compile --coerce --input scalable-group-name-input="Scalable Group" ./scalable.yaml 
PROBLEMS (1)
  file:///home/bernardodemarco/code/puccini-example/scalable.yaml
    @15,7 service_template.inputs["scalable-group-name-input"].validation: unsupported keyname
puccini-tosca validate --input scalable-group-name-input="Scalable Group" ./scalable.yaml
➜  puccini-tosca validate --input scalable-group-name-input="Scalable Group" ./scalable.yaml
PROBLEMS (1)
  file:///home/bernardodemarco/code/puccini-example/scalable.yaml
    @15,7 service_template.inputs["scalable-group-name-input"].validation: unsupported keyname

Once the validation clause is removed, both validation and compilation execute correctly:

Service template without any validation clauses
tosca_definitions_version: tosca_2_0

node_types:
  Scalable:
    properties:
      scalable-group-name:
        type: string
        required: true

service_template:
  inputs:
    scalable-group-name-input:
      type: string
      required: true
      # validation: { $greater_or_equal: [ { $length: [ $value ] }, 3 ] }
  node_templates:
    scalable-virtual-machine-group:
      type: Scalable
      properties:
        scalable-group-name: { $get_input: [ scalable-group-name-input ] }
puccini-tosca compile --input scalable-group-name-input="Scalable Group" ./scalable.yaml
➜  puccini-tosca compile --input scalable-group-name-input="Scalable Group" ./scalable.yaml 
version: "1.0"
metadata:
# Clout output
# (...)                          
puccini-tosca validate --input scalable-group-name-input="Scalable Group" scalable.yaml
➜  puccini-tosca validate --input scalable-group-name-input="Scalable Group" ./scalable.yaml
valid

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions