I don't think we should just be thinking about a use-case like the CA server, which is maybe more limited in behaviour than the more general idea here of being able to call effectors.
In particular, what if you wanted to embed the effector invocation on some entity within the code for an effector of your own entity? i.e. you have an effector on entity A that does some stuff when invoked, including invoking an effector on entity B? (And maybe using the result when calculating its own result instead of storing it in a sensor). Is that something we'd want to support? Is it a "stage 2" thing we would add later on, some time after implementing the EntityInitializer approach? G On Wed, 1 Mar 2017 at 12:32 Alex Heneveld <[email protected]> wrote: An `EntityInitializer` for this purpose is a nice alternative pattern -- better than the child entity I suggested at #155 -- until we have sequence effector YAML. Is there anything `$brooklyn:effector` gives us that an initializer wouldn't do in a cleaner way? Best Alex On 1 March 2017 at 11:54, Aled Sage <[email protected]> wrote: > Hi all, > > I'd like to resurrect the discussion of whether the yaml DSL should > support invoking effectors. > > See https://github.com/apache/brooklyn-server/pull/155. (That was merged, > but Alex will revert it while we discuss if we want it, and if so then how > it would behave). > > If folk have additional use-cases and opinions to share, that would be > very useful! > > --- > > Below is what Andrew wrote in his email "[PROPOSAL] Enabling Effective > Effectors" on 30/05/2016, but it wasn't properly discussed then. > > ## Calling Effectors > > The YAML blueprint specification allows entities to be defined with > sensors > and to access the value of sensors for use in configuration. However, > although an entity can include effectors defined in the Java classes, or > using scripting languages (see above) and SSH commands, it is not > possible > to execute effectors and retrieve their results anywhere in a blueprint. > > The code in [brooklyn-server#155]( > https://github.com/apache/brooklyn-server/pull/155) implements a new > function for the `DslComponent` class that can execute an effector on an > entity and evaluates to its return value. This new function is used as > follows: > > ```YAML > $brooklyn:entity("other").effector("findInformation"): > args: > arg1: "value" > arg2: 3.14159d > arg3: $brooklyn:attributeWhenReady("host.address") > ``` > > Here we see the effector `findInformation` being evaluated with three > arguments, on the entity with id `other`. One of the arguments is an > `attributeWhenReady` call, thus causing the execution to be delayed > until > the sensor data is available. > > --- > Alex's philosophical objection in https://github.com/apache/broo > klyn-server/pull/155#issuecomment-283077136 is copied below for your > convenience): > > right, so the use case is one entity wanting to get information from > another. is there no way this can be accommodated using sensors? my > philosophical objection is that we're introducing first-class > support for a new class of dependency injection: > > 1. simplest - static: DEP.x is set to a constant > 2. blocking - sensor: DEP.x can wait if a value isn't ready yet, ie > it is a promise, $brooklyn:entity(SRC).attributeWhenReady(...), > which once resolved is always taken as the value > 3. triggering - effector: every lookup to DEP.x invokes a call > somewhere eg $brooklyn:entity(SRC).effector(...) > > A widespread use of (3) scares me [Alex] and it's worth avoiding > this if at all possible. it also means lookups aren't idempotent > (which is why the SideEffecting marker is introduced here, but it > isn't going to work. > > could your [use-case] be solved another way, if not with waiting on > a sensor, by the config pointing at the source entity rather than > the key value itself, and whenever it is accessed there is code > which invokes the effector to get the key on that source entity? > > > --- > I believe the original use-case that motivated this was setting up a > docker host, with certificates dynamically generated by a CA Server > (Certificate Authority). > > The blueprint has a CA Server entity and several Docker Host entities. For > setting up each Docker Host, we want a new certifiacte that is signed by > the CA. We want to put the certificate files onto the Docker Host (so that > the Docker Engine is correctly configured for TLS). > > There is an effector on the CA entity, to send it a Certificate Signing > Request (CSR), and thus to get back a new certificate. > > One solution in pure-yaml blueprints (simplified slightly for clarity in > this discussion) would be to have a "certificate" config key on the Docker > Host entity. This would be set to a value like: > > brooklyn.config: > certificateData: > $brooklyn:entity("ca").effector("requestCertificate"): > args: > ip: $brooklyn:config("host.address") > > Part of the setup script would use this config key, and create a file > using its value. > > When the config key was evaluated for the first time, it would execute the > effector and thus get a new certificate. Subsequent lookups of the config > key would use the same value (rather than invoking the effector multiple > times). > > Note the significant difference compared to Alex's summary, where Alex > suggested the effector would be invoked every time the config key value was > retrieved. > > === > Below are some alternative ways to solve the above use-case. I don't want > us to get too distracted in this discussion of "yaml DSL for invoking > effectors". However, if we reach agreement that one of these alternative is > better then we can ignore the use-case that I've described above. > > _*Resort to Java*_ > We could resort to writing some Java code (e.g. write an > "EntityInitializer" that called the requestCertificate effector, and set > the result as a sensor; this could be added to the Docker Host entity. The > rest of the Docker Host blueprint would use attributeWhenReady on the > "certificateData" sensor. > > There could be a generic EntityInitializer for invoking a given effector > on a given entity, and setting a sensor with the result. > > _*Defining an Effector as a Sequence of Tasks*_ > Longer term, we could add YAML support for describing a sequence of tasks. > The basic Docker Host entity would be extended so that its "start" effector > first invoked a task, which would call the "requestCertificate" effector on > the CA (and probably set the result as a sensor or config key). > >
