[openstack-dev] [Heat] [TripleO] Extended get_attr support for ResourceGroup

Zane Bitter zbitter at redhat.com
Tue Jul 15 18:01:58 UTC 2014


On 14/07/14 12:21, Tomas Sedovic wrote:
> On 12/07/14 06:41, Zane Bitter wrote:
>> On 11/07/14 09:37, Tomas Sedovic wrote:

[snip]

>>> 3. List of IP addresses of all controllers:
>>>
>>> https://github.com/openstack/tripleo-heat-templates/blob/a7f2a2c928e9c78a18defb68feb40da8c7eb95d6/overcloud-source.yaml#L405
>>>
>>>
>>> We cannot do this, because resource group doesn't support extended
>>> attributes.
>>>
>>> Would need something like:
>>>
>>>       {get_attr: [controller_group, networks, ctlplane, 0]}
>>>
>>> (ctlplane is the network controller_group servers are on)
>>
>> I was going to give an explanation of how we could implement this, but
>> then I realised a patch was going to be easier:
>>
>> https://review.openstack.org/#/c/106541/
>> https://review.openstack.org/#/c/106542/
>
> Thanks, that looks great.
>
>>
>>> 4. IP address of the first node in the resource group:
>>>
>>> https://github.com/openstack/tripleo-heat-templates/blob/a7f2a2c928e9c78a18defb68feb40da8c7eb95d6/swift-deploy.yaml#L29
>>>
>>>
>>> Can't do: extended attributes are not supported for the n-th node for
>>> the group either.
>>
>> I believe this is possible today using:
>>
>>    {get_attr: [controller_group, resource.0.networks, ctlplane, 0]}
>
> Yeah, I've missed this. I have actually checked the ResourceGroup's
> GetAtt method but didn't realise the connection with the GetAtt function
> so I hadn't tried it before.
>

[snip]

>>
>>> Alternatively, we could extend the ResourceGroup's get_attr behaviour:
>>>
>>>       {get_attr: [controller_group, resource.0.networks.ctlplane.0]}
>>>
>>> but the former is a bit cleaner and more generic.
>>
>> I wrote a patch that implements this (and also handles (3) above in a
>> similar manner), but in the end I decided that this:
>>
>>    {get_attr: [controller_group, resource.0, networks, ctlplane, 0]}
>>
>> would be better than either that or the current syntax (which was
>> obviously obscure enough that you didn't discover it). My only
>> reservation was that it might make things a little weird when we have an
>> autoscaling API to get attributes from compared with the dotted syntax
>> that you suggest, but I soon got over it ;)
>
> So now that I understand how this works, I'm not against keeping things
> the way we are. There is a consistency there, we just need to document
> it and perhaps show some examples.

It kind of fell out of the work I was doing on the patches above anyway. 
It would be harder to _not_ implement this (and the existing way still 
works too).

>>
>>> ---
>>>
>>>
>>> That was the easy stuff, where we can get by with the current
>>> functionality (plus a few fixes).
>>>
>>> What follows are examples that really need new intrinsic functions (or
>>> seriously complicating the ResourceGroup attribute code and syntax).
>>>
>>>
>>> 5. Building a list of {ip: ..., name: ...} dictionaries to configure
>>> haproxy:
>>>
>>> https://github.com/openstack/tripleo-heat-templates/blob/a7f2a2c928e9c78a18defb68feb40da8c7eb95d6/overcloud-source.yaml#L478
>>>
>>>
>>> This really calls for a mapping/for-each kind of functionality. Trying
>>> to invent a ResourceGroup syntax for this would be perverse.
>>>
>>> Here's what it could look like under Clint's `map` proposal:
>>>
>>>       map:
>>>       - ip: {get_attr: [{get_resource: "$1"}, networks, ctlplane, 0]
>>>         name: {get_attr: [{get_resource: "$1"}, name]}
>>>       - {get_attr: [compute_group, refs]}
>>
>> This has always been the tricky one :D
>>
>> IMHO the real problem here is that we're trying to collate the data at
>> the point where it is consumed, not the point where it is produced. It's
>> not like we were just given a big blob of data and now have to somehow
>> extract the useful parts; we produced it ourselves by combining data
>> from the scaled units. If we didn't get the right data, we have only
>> ourselves to blame ;)
>>
>> So if the provider template that defines e.g. a compute node contains
>> the section:
>>
>>    outputs:
>>      host_entry:
>>        value:
>>          ip: {get_attr: [compute_server, networks, ctlplane, 0]}
>>          name: {get_attr: [compute_server, name]}
>>
>> Then in your main template all you need to do is:
>>
>>    {getattr: [compute_group, host_entry]}
>
> Oh this is absolutely wonderful. I've had all the pieces in my head but
> I didn't make the connection.
>
> You're completely right about using a provider template here anyway --
> that's what I planned to do, but I didn't fully appreciate the
> connection between outputs and attributes (even though I knew about it).
>
>>
>> to get the list of {ip: ..., name: ...} dicts. (As a bonus, this is
>> about as straightforward to read as I can imagine it ever getting.)
>>
>> Note that you *will* want to be using a provider template as the scaled
>> unit _anyway_, because each compute_server will have associated software
>> deployments and quite possibly a bunch of other resources that need to
>> be in the scaled unit.
>
> Yep, exactly.
>
>>
>> There is one aspect of this that probably doesn't work yet: originally
>> outputs and attributes were only allowed to be strings. We changed that
>> for attributes, but probably not yet for outputs (even though outputs of
>> provider templates become attributes of the facade resource). But that
>> should be easy to fix. (And if your data can be returned as a string, it
>> should already work.)
>
> Unless I misunderstood what you're saying, it seems to be working now:
>
> controller.yaml:
>
>      outputs:
>        hosts_entry:
>          description: An IP address and a hostname of the server
>          value:
>            ip: {get_attr: [controller_server, networks, private, 0]}
>            name: {get_attr: [controller_server, name]}
>
> environment.yaml:
>
>      resource_registry:
>        OS::TripleO::Controller: controller.yaml
>
> test-resource-group.yaml:
>
>      resources:
>        servers:
>          type: OS::Heat::ResourceGroup
>          properties:
>            count: 3
>            resource_def:
>              type: OS::TripleO::Controller
>              properties:
>                key_name: {get_param: key_name}
>                image: {get_param: image_id}
>
>      outputs:
>        hosts:
>          description: "/etc/hosts entries for each server"
>          value: {get_attr: [servers, hosts_entry]}
>
> Heat stack-show test-resource-group:
>
>     {
>       "output_value": [
>         "{u'ip': u'10.0.0.4', u'name':
> u'rg-7heh-0-tweejsvubaht-controller_server-mscy33sbtirn'}",
>         "{u'ip': u'10.0.0.3', u'name':
> u'rg-7heh-1-o4szl7lry27d-controller_server-sxpkalgi27ii'}",
>         "{u'ip': u'10.0.0.2', u'name':
> u'rg-7heh-2-l2y6rqxml2fi-controller_server-u4jcjacjdrea'}"
>       ],
>       "description": "/etc/hosts entries for each server",
>       "output_key": "hosts"
>     },

It looks like the dicts are being converted to strings by Python, so 
there probably is a small bug here to be fixed. (At the very least, if 
we're converting to strings we should do so using json.dumps(), not repr().)

[snip]

>>>
>>> So this boils down to 4 features proposals:
>>>
>>> 1. Support extended attributes in ResourceGroup's members
>>
>> Sorted.
>
> Yep
>
>>
>>> 2. Allow a way to use a Resource ID (e.g. what you get by {get_attr:
>>> [ResourceGroup, refs]} or {get_attr: [ResourceGroup, resource.0]}) with
>>> existing intrinsic functions (get_resource, get_attr)
>>
>> No dice, but (1) solves the problem anyway.
>
> Agreed
>
>>
>>> 3. A `map` intrinsic function that turns a list of items to another list
>>> by doing operations on each item
>>
>> There may be a better solution available to us already, so IMO
>> investigate that first. If that turns out not to be the case then we'll
>> need to reach a consensus on whether map is something we want.
>
> You're right. I no longer think map (or anything like it) is necessary.

That's the kind of thing I love to hear :D

>>> 4. A `concat_list` intrinsic function that joins multiple lists into one.
>>
>> Low priority.
>
> Yeah.
>
>>
>>> I think the first two are not controversial. What about the other two?
>>> I've shown you some examples where we would find a good use in the
>>> TripleO templates. The lack of `map` actually blocks us from going
>>> all-Heat.
>>
>> Hopefully that's not actually the case.
>>
>>> The alternative would be to say that this sort of stuff to be done
>>> inside the instance by os-apply-config et al. It would complicate things
>>> for TripleO, but oh well.
>>
>> It seems to me that the alternative is not necessarily to modify
>> os-apply-config, but rather to provide a software config with a script
>> that converts the data from whatever format Heat can supply to whatever
>> format is needed by the application. Although I don't think it's even
>> required in the specific case you mention, I find that a much better
>> answer for the general case than turning the template format into the
>> JSON equivalent of XSLT ;)
>
> That's what I thought -- not rewriting os-apply-config but simply
> passing the raw data to it and changing the tripleo image elements to
> output the configuration format required by the applications.
>
> +1 on the XSLT sentiment, I just didn't realise we pretty much solve
> everything with the existing model (hat off to the design btw, I love
> how it works together -- we just maybe need to communicate it a bit more).

Yeah, we're thinking of trying to put something together for the summit 
to explain how the pieces fit together. You're not the only one looking 
for that documentation, I suspect :)

cheers,
Zane.



More information about the OpenStack-dev mailing list