OASIS Topology and Orchestration Specification for Cloud Applications (TOSCA) TC

  • 1.  RE: [tosca] Substitution Inputs

    Posted 04-18-2021 19:28




    Hi Tal, comments inline
     

    From: Tal Liron <tliron@redhat.com>

    Sent: Tuesday, April 13, 2021 11:30 AM
    To: Chris Lauwers <lauwers@ubicity.com>
    Cc: tosca@lists.oasis-open.org
    Subject: Re: [tosca] Substitution Inputs

     


    OK, I did not realize this. I'm looking at the spec for TOSCA 1.2 and 1.3 on this ([3.8.8]) and it's very confusing.


     



    TOSCA 1.2 supported two notations, one for a "normal" mapping to a template, and another for mapping to inputs. In TOSCA 1.3 the first notation was removed, likely to remove confusion ... but it also removes this feature, so now it's impossible to map properties
    to anything other than inputs. Attribute mapping remained the same (map to an attribute or an output). Also it seems that attribute mappings allow for mapping to capability and even relationship attributes (nested).

    The reason that direct property-to-property mappings were removed is because they don t work: the starting assumption is that a substituting template needs to be a valid TOSCA template,
    independent of substitution mapping. This means that all required properties must have values assigned. If property mappings were to assign different values to those same properties, then we have a conflict resulting in non-deterministic behavior. Mapping
    all properties through inputs is the only way to make this work consistently.
    In addition, the 1.3 spec does not actually define attribute mappings as part of substitution mappings. It makes reference to attribute mapping syntax, but the only attribute mapping
    syntax defined in the spec is for mapping operation outputs to attributes on node or relationships. The attribute mapping aspect of substitution mapping needs a lot more discussion. In my implementation, I don t support attribute mappings. Instead, I use
    the outputs defined in a service template and map them onto the operation outputs for the create operation in the substituted node. In my opinion, this is the only approach that makes sense, but it results in asymmetry between handling of inputs and outputs.



    This seems to me a hijacking of the properties feature (and attributes for that matter) for an entirely different purpose. Moreover it would require the node type to be designed in such a way that it would have
    to match inputs ... or vice versa. This seems a very roundabout way to solve the problem.
    This shouldn t affect node type design. It is the responsibility of the substituting template to make sure all its required input values can be obtained from a property value in the substituted node somehow.


     


    I'm inclined more and more to think that we need a very different grammar for linking the consuming service and providing service.
    We should not think of this in terms of client/server or consuming service/providing service . This is simple decomposition (component/system pattern), nothing more, nothing less.


     


    I think what we need here is a way for the providing service to "expose" features and also for the consuming template to "inject" them. These features thus become "shared" between both services. And I think Adam's
    proposal is the right starting point, something that looks more like a node template than a node type, something that can be constructed rather than "mapped".
    Again, in my opinion this is not the correct way to think about this. The substituted node doesn t care (nor should it have to) about the features of the substituting template. The substituting template is strictly
    an implementation of the features exposed by the substituted node. There is no injection of anything, just implementation.



     


    One major problem with the current grammar is that mappings are one-to-one, but real world use cases are ... more complicated. But also more simple in terms of defining what users want. Here's a simple example:
    imagine a providing service that has two nodes, an application and a database, and that boths of these can be installed on the same server. The consuming service doesn't care that internally the providing service comprises several nodes, all it wants to do
    is specify "install this (whole) service on this server". There is no way to do this with substitution mapping, because you can only map the installation requirement of either node template, not both of them at once. There's this mismatch between "mapping"
    and the control of the actual features we need.
    The pattern of install a bunch of things on the same server is independent of substitution mapping. The current solution in TOSCA is to use selectable nodes for this purpose. However, we don t have a way (as
    part of substitution mapping) to map a requirement onto a selectable node. However, there are other mechanisms to accomplish the same result (using node filters).


     


    Allow me to try to solve this with some back-of-the-napkin brainstorming by building on Adam's proposal and my idea of "exposing":


     


    # Providing service


    topology_template:


      inputs:


        cores:


          type: integer


          default: { @get_property: [ app, cores ] }


     

      node_templates:


        app:


          directives:


          - expose # shared with the consuming service


          type: WebApplication # this type derives from "Application"


          properties:


            name: { @get_property: [ database,  capabilityname, name ] }


            cores: 1


          attributes:


            id: { @get_attribute: [ database, capabilityname, nested1, nested2, id ] }


         requirements:


         - host: my-host


     

        database:


          type: DB





         requirements:


         - host: myhost



     


       my-host:


          directives:


          - expose # *also* shared with the consuming service


          type: Machine


         



    # Consuming service


    topology_template:


      node_templates:

        myservice:

          type: Application


          properties:


            cores: 5 # this will and override the value (our values here are higher priority), and thus also the property, which will then affect the input


          requirements:


          - host: my-vm



     


       my-vm:


          type: VirtualMachine # this type derives from "Machine" and the node will be "injected" into the providing template



     



    If you follow this example you'll see that rather than substituting a single node, we are instead "exposing" *two* nodes from the providing service.

    This implements a very different paradigm than what we re trying to do with substitution mapping, in my opinion. The minute you talk about exposing you now assume that the substituted
    node will be aware of what is exposed by the substituting template. This violates the idea of abstraction that is the foundation of substitution mapping. The whole point is that a substituted node doesn t care about how it is implemented internally.


    Once exposed they are essentially "shared" between the two services. The node template names are different but as long as the matching can be done correctly (by policy?) they should end up referring to the same exact node representations. Also note that the
    node types have to be the same or *derive from each other*. Of course references to the base type won't be able to access features of the derived type, but that is intended by design. So the consuming service only knows that this is an (abstract) "Application",
    while the providing template uses "WebApplication" and refers to additional properties and attributes. On the flip side, the providing service knows that it connects to an (abstract) "Machine", while the consuming service provides a concrete sub-type, "VirtualMachine".


    The magic of sharing means that we can indeed install both the app and db nodes on the same server. And we're no longer talking about "substitution nodes" but rather a more open sharing of one or more nodes between
    the two services.
    If sharing is your goal, then you should use requirement fulfillment (likely using selectable nodes), not substitution mapping. The objective of these two (very different) features is not the same.


     


    On Tue, Apr 13, 2021 at 11:54 AM Chris Lauwers < lauwers@ubicity.com > wrote:




    This is exactly what property mappings are for. The required inputs for the substituting template are obtained from the property values of the substituted node.
     
    Thanks,
     
    Chris
     

    From:
    tosca@lists.oasis-open.org < tosca@lists.oasis-open.org >
    On Behalf Of Tal Liron
    Sent: Tuesday, April 13, 2021 9:48 AM
    To: tosca@lists.oasis-open.org
    Subject: [tosca] Substitution Inputs

     


    Hello ad-hoc folk,


     


    In our discussion today about substitution mappings I forgot to mention a gaping hole in the spec:



    what if the substituted topology template has required inputs? There is no standard way in TOSCA to specify them.


     


    In Turandot, since I am using policies anyway (the directives are wholly insufficient), I use a

    custom policy property for this feature.


     


     












  • 2.  Re: [tosca] Substitution Inputs

    Posted 04-18-2021 19:45
    On Sun, Apr 18, 2021 at 2:28 PM Chris Lauwers < lauwers@ubicity.com > wrote: If sharing is your goal, then you should use requirement fulfillment (likely using selectable nodes), not substitution mapping. The objective of these two (very different) features is not the same. The goal is service composition, which indeed involves abstraction. But substitution mapping, as it is right now, is extremely limited in functionality (and also confusing). We rely on "mapping" as the exposing mechanic, but it's limited and it overlaps with our explicit methods of mapping values -- functions like get_property and get_attribute. You can prefer say that we are not "injecting" values, but that's what ends up happening. You are just insisting that we only "expose" things through an existing node template (mapping properties and attributes to inputs and outputs). It's limited and also very non-deterministic. As you point out, "It is the responsibility of the substituting template to make sure all its required input values can be obtained from a property value in the substituted node somehow." This is quite a bit of responsibility! You would end up only finding out that you did something wrong in runtime, when composition actually happens. This seems to go against what we hope to achieve in TOSCA, that all designs can be validated during design-time.