oasis-open / tosca-community-contributions

OASIS TC Open Repository: Manages TOSCA profiles, tests, and templates that are maintained by the TOSCA community. They are intended to be used as examples to help developers get started with TOSCA and to test compliance of TOSCA implementations with the standard.
https://github.com/oasis-open/tosca-community-contributions
Apache License 2.0
39 stars 25 forks source link

Function notation: prefix character #67

Closed aszs closed 2 years ago

aszs commented 2 years ago

TOSCA is currently broken. There is no way to provide a value that happens to look like a function call. For example:

node_types:
  Server:
    properties:
      traits:
        type: map
        entry_schema:
          type: list
          entry_schema: string

service_template:
  node_templates:
    server:
      type: Server
      properties:
        trait:
          concat: [ this, is, supposed, to, be, a, value ]

In TOSCA 1.X, that last line will always be evaluated as a function call. It cannot be escaped in any way.

The proposal is to require all function calls (both intrinsic and custom) in TOSCA to begin with an escapable prefix character. This will solve the above bug, and also provide a more consistent parsing algorithm for functions (both for TOSCA processors and for the human eye scanning a TOSCA YAML file).

The proposed prefix character is $. It would not cause any problems with YAML parsing, and also it would be familiar to users of bash, Perl, Ruby, and many templating languages.

I think a programmatic definition makes the most sense:

(extracted from issue #123)

In TOSCA values, for any map of any nested depth:

Note that I am here assuming that the argument(s) of a function can be anything: a single string value (like get_input), a sequence (like all other intrinsic functions), or anything else (for custom functions). I think this is a good idea, as it allows for cleaner syntax, e.g. functions with single arguments (like get_input) but also functions with a map argument (compare to kwargs in Python):

{ $get_security_context: { env: staging, role: admin } }
tliron commented 2 years ago

An alternate proposal could be that all functions (both intrinsic and custom) must have a YAML seq for arguments (and the get_input function would have to be changed to match that):

I am less in favor of this. I don't think there's any ambiguity in the original programmatic definition.

tliron commented 2 years ago

Also a clarification about escaping the $: you would only need to do this for map keys, not for any arbitrary string value. Examples:

properties:
  prop1: $myid # valid as is, no need to escape
  prop2: my_value

But here we do need to escape:

properties:
  $$prop1: myid # if we don't escape we will get a "malformed function" syntax error
  prop2: my_value
tliron commented 2 years ago

This has been accepted into the spec. Also implemented in Puccini.

lauwers commented 2 years ago

Actually, one more clarifying question: I assume function names can be namespaced, as in ubct:$sqrt

tliron commented 2 years ago

I don't assume that, at least not for built-in (including custom built-in) functions. It is something we should discuss for user-defined declared functions (#123).

Should the functions section work like the _types sections in that they are namespaced? If so, I would suggest this syntax:

$ubct:sqrt

because it wouldn't break the algorithm and wouldn't complicate escaping.