[openstack-dev] [heat][tripleo]Recursive validation for easier composability

Steven Hardy shardy at redhat.com
Tue Jun 23 11:06:27 UTC 2015

On Mon, Jun 22, 2015 at 01:21:29PM -0400, Jay Dobies wrote:
> On 06/22/2015 12:19 PM, Steven Hardy wrote:
> >Hi all,
> >
> >Lately I've been giving some thought to how we might enable easier
> >composability, and in particular how we can make it easier for folks to
> >plug in deeply nested optional extra logic, then pass data in via
> >parameter_defaults to that nested template.
> >
> >Here's an example of the use-case I'm describing:
> >
> >https://review.openstack.org/#/c/193143/5/environments/cinder-netapp-config.yaml
> >
> >Here, we want to allow someone to easily turn on an optional configuration
> >or feature, in this case a netapp backend for cinder.
> I think the actual desired goal is bigger than just optional configuration.
> I think it revolves more around choosing a nested stack implementation for a
> resource type and how to manage custom parameters for that implementation.
> We're getting into the territory here of having a parent stack defining an
> API that nested stacks can plug into. I'd like to have some sort of way of
> deriving that information instead of having it be completely relegated to
> outside documentation (but I'm getting off topic; at the end I mention how I
> want to do a better write up of the issues Tuskar has faced and I'll
> elaborate more there).

I guess I've been thinking of it in terms of two sides of the same problem,
but I see from the responses that Thomas and Steve made that we could
consider this "realization of an interface" part seperately.

I was thinking that if you have sufficient parameter introspection
capabilities then you know implicitly which templates satisfy a particular
interface, based on the parameters schema exposed - essentially relying on
duck-typing such that if a subset of a templates parameters (and parameter
types) match what the parent stack provides, then it's a valid
implementation.  Clearly this is a considerably less strict approach than
that described in the tosca docs Thomas referenced, but it's potentially
simpler and more flexible too?

> >The parameters specific to this feature/configuration only exist in the
> >nested cinder-netapp-config.yaml template, then parameter_defaults are used
> >to wire in the implementation specific data without having to pass the
> >values through every parent template (potentially multiple layers of
> >nesting).
> >
> >This approach is working out OK, but we're missing an interface which makes
> >the schema for parameters over the whole tree available.
> >
> >This is obviously
> >a problem, particularly for UI's, where you really need a clearly defined
> >interface for what data is required, what type it is, and what valid values
> >may be chosen.
> I think this is going to be an awesome addition to Heat. As you alluded to,
> we've struggled with this in TripleO. The parameter_defaults works to
> circumvent the parameter passing, but it's rough from a user experience
> point of view since getting the unified list of what's configurable is
> difficult.

Yeah, I guess enhancing our pre-create template introspection/validation is
what I'm trying to focus on as a "first step" in improvinig that rough user

> >I'm considering an optional additional flag to our template-validate API
> >which allows recursive validation of a tree of templates, with the data
> >returned on success to include a tree of parameters, e.g:
> >
> >heat template-validate -f parent.yaml -e env.yaml --show-nested
> >{
> >   "Description": "The Parent",
> >   "Parameters": {
> >     "ParentConfig": {
> >       "Default": [],
> >       "Type": "Json",
> >       "NoEcho": "false",
> >       "Description": "",
> >       "Label": "ExtraConfig"
> >     },
> >     "ControllerFlavor": {
> >       "Type": "String",
> >       "NoEcho": "false",
> >       "Description": "",
> >       "Label": "ControllerFlavor"
> >     }
> >   }
> >  "NestedParameters": {
> >     "child.yaml": {
> >         "Parameters": {
> >           "ChildConfig": {
> >           "Default": [],
> >           "Type": "Json",
> >           "NoEcho": "false",
> >           "Description": "",
> >           "Label": "Child ExtraConfig"
> >           }
> >         }
> >      }
> >}
> Are you intending on resolving parameters passed into a nested stack from
> the parent against what's defined in the nested stack's parameter list? I'd
> want NestedParameters to only list things that aren't already being
> specified to the parent.

This is a good point - I was assuming we'd expose all parameters, not only
those which aren't specified by the parent.

> Specifically with regard to the TripleO Heat templates, there is still a lot
> of logic that needs to be applied to properly divide out parameters. For
> example, there are some things passed in from the parents to the nested
> stacks that are kinda namespaced by convention, but its not a hard
> convention. So to try to group the parameters by service, we'd have to look
> at a particular NestedParameters section and then also add in anything from
> the parent that applies to that service. I don't believe we can use
> parameter groups to correlate them (we might be able to, or that might be
> its own improvement).

I think we probably can use parameter groups to namespace related
parameters, including accross multiple templates.

Also, we might consider adding an automatically generated parameter group,
which solves the "specified by parent" problem by defining a group of
parameters which have (or have not) been provided by the parent resource?

> I realize that's less of a Heat issue and more of a THT issue, but I figured
> I'd bring it up anyway.
> >This implies that we also need to pass the "files" map to the validate API,
> >like we currently do for create (we already pass the environment, although
> >it's not really doing much beyond providing parameters for the parent stack
> >AFAICT, we completely skip validating TemplateResources because the files
> >aren't passed):
> >
> >https://github.com/openstack/heat/blob/master/heat/engine/service.py#L873
> >
> >Before I go ahead and spend time writing a spec/code for this, what do
> >folks think about enhancing validate like this?  Is there an alternative,
> >for example adding a parameters schema output to stack-preview?
> For what it's worth, I'd rather see this as a spec before code. There are a
> lot of complications we hit in Tuskar in trying to make configuring the
> overcloud through THT user-friendly. This is one part of it, but there are
> others. I'd like to have them all talked out and see what the larger group
> of changes are.

Sure, I'm hoping we can work out the initial details here, then I'm very
happy to raise some specs.  It may also prove useful to hack on some PoC
code to clarify discussions, but I'm happy to start with specs.

> For example, take the cinder-netapp-config example you mentioned. That can
> only be used to fulfill a specific resource type in the registry. That
> knowledge isn't captured anywhere, so it relies on some sort of external
> documentation saying "choose from these two child stacks for X, choose from
> these three for Y". That's something that Tuskar going forward is going to
> need to capture, but that also might be another candidate for adding to Heat
> and helping the user experience for complex nested stacks in general.

Yeah this is true, but I guess I'm attempting to avoid implementing a
full-on type matching system here, instead my idea is more to allow easier
composition of multiple environment files, which contain all the pieces
needed to enable a specific feature or configuration.

For example, say the cinder-netapp-config.yaml environment file was
actually renamed to e.g


Or similar.  My idea is that we could throw all available template
"fragments" into Swift in the undercloud, then have a UI capable of
building an interface dynamically based on what is found.

For example, the above template structure and naming would be interpreted
as creating a page with various cinder backends and an "enable netapp"

I think most of that is already possible, but what we can't do is
introspect the tree of templates to figure out what extra parameters we
need to ask the user for (related to your "specified by parent" problem

The other problem with this approach is we need a way to chain multiple
templates together - for example if we have multiple cinder backends, how
do we include multiple enable_foo environments without overwriting?

One option would be a special resource_registry syntax which allows you to
specify a list of implementations, e.g:

OS::TripleO::EnableCinderBackends: [enable_netapp.yaml, enable_foo.yaml, ...]

This would internally generate a nested stack which passes the same
properties/parameters into each template in turn (depends_on to respect
list ordering).

This could then be combined with some smarter environment merging
capabilities in python-heatclient, e.g such that lists can be appended
instead of overwritten:

heat stack-create overcloud -f overcloud.yaml -E enable_netapp.yaml -E

-E would be a new mode of the existing "-e" option which knows how to
attempt merging those environment entries which can be merged/appended.

> Perhaps this is another argument for a schema of sorts, which is why I'd
> like to see us lay all of these issues out at the same time in specs before
> any code is written on a particular implementation. I'll try to find time in
> the next few days to do a better write up of the kinds of questions that
> Tuskar had to try to answer about the THT templates.

Yup, my question is basically is the existing template parameter schema
sufficient, combined with some judicous use of directory hierarchy and
naming conventions, or do we need the stricter (and more complex from a
template author perspective) approach mentioned by Thomas and Steve?

My feeling is we should at least consider the "tree of templates" approach
before jumping into adding yet-more complexity to already really complex
templates via explicit interface definitions for everything.


More information about the OpenStack-dev mailing list