ResourceGroup attributes don't work with index lookups

Bug #1640488 reported by Steven Hardy
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
OpenStack Heat
New
Low
Unassigned

Bug Description

We seem to have an issue with order of evaluation the path-based index for outputs where a list is generated, e.g:

[stack@instack ~]$ cat rg.yaml
heat_template_version: 2016-10-14

resources:
  rg:
    type: OS::Heat::ResourceGroup
    properties:
      count: 3
      resource_def:
        type: OS::Heat::Value
        properties:
          value: foo

outputs:
  test_out_list:
    value: {get_attr: [rg, value]}
  test_out_zero:
    value: {get_attr: [rg, value, 0]}

[stack@instack ~]$ openstack stack output show rg1 test_out_list
+--------------+----------------------+
| Field | Value |
+--------------+----------------------+
| description | No description given |
| output_key | test_out_list |
| output_value | [ |
| | "foo", |
| | "foo", |
| | "foo" |
| | ] |
+--------------+----------------------+
[stack@instack ~]$ openstack stack output show rg1 test_out_zero
+--------------+----------------------+
| Field | Value |
+--------------+----------------------+
| description | No description given |
| output_key | test_out_zero |
| output_value | [ |
| | "f", |
| | "f", |
| | "f" |
| | ] |
+--------------+----------------------+

I expected test_out_zero to return "foo" e.g the first list item, but it's evaluating it for each item inside the group.

I seem to recall a similar bug about this in the past, but failed to locate it.

If this is expected behaviour we should at least document it, perhaps showing how to do the list lookup with yaql instead.

Revision history for this message
Thomas Herve (therve) wrote :

Yeah that behavior looks correct to me. It is indeed a bit confusing with regard to the regular get_attr behavior, but it behaves fairly differently on stack resources in general.

Fortunately you don't need yaql. You can either do:

{get_attr: [rg, 'resource.0', value]}

Or

  rg_val:
    type: OS::Heat::Value
    properties:
      value: {get_attr: [rg, value]}

{get_attr: [rg_val, value, 0]}

Changed in heat:
importance: Undecided → Low
milestone: none → ocata-1
Revision history for this message
Rabi Mishra (rabi) wrote :

Yeah this has been discussed earlier too and documenting it would be help. I assume specifying as below would work, no?

value: {get_attr: [rg, resource.0, value]}

Revision history for this message
Rabi Mishra (rabi) wrote :

@therve, I did not see your comment before posting mine;)

Revision history for this message
Steven Hardy (shardy) wrote :

> {get_attr: [rg, 'resource.0', value]}

Yeah this is what TripleO already does, but there's a subtle problem here - the "0" doesn't refer to a list index, it refers to a resource name "0" in the nested stack. So this breaks if you ever remove that node from the group via removal_policies (ref https://bugs.launchpad.net/tripleo/+bug/1640449)

> rg_val:
> type: OS::Heat::Value
> properties:
> value: {get_attr: [rg, value]}
>
> {get_attr: [rg_val, value, 0]}

Hmm, yeah this may work, as what we want is the first item in the list, independent of the group member naming.

I also have a yaql workaround, but it's probably more ugly than the OS::Heat::Value approach. One question - what does the value return during validation? If it's None I'm wondering if the index lookup in the second get_attr will fail? (I had to work around that in my yaql solution):

      input_values:
        bootstrap_nodeid:
          yaql:
            expression: coalesce($.data, [''])[0]
            data: {get_attr: [{{role.name}}, hostname]}

Revision history for this message
Steven Hardy (shardy) wrote :

So the OS::Heat::Value workaround doesn't work, because during validation the index "0" doesn't exist, see https://review.openstack.org/#/c/395699/

Deployment fails with:

ERROR: resources.BlockStorageAllNodesDeployment.Properties.input_values.bootstrap_nodeid.get_attr: : The Referenced Attribute (BlockStorageHostnameDetails 0) is incorrect."

So I suspect we'll be forced to go with the yaql approach unless we can figure out a cleaner workaround?

All I want is to get the first resource from the group, without hard-coding a name for a group member which may subsequently get removed.

Revision history for this message
Zane Bitter (zaneb) wrote :

I think the ultimate answer is to stop using removal policies and mark resources as unhealthy instead.

Revision history for this message
Steven Hardy (shardy) wrote :

> I think the ultimate answer is to stop using removal policies and mark resources as unhealthy instead.

Long term you may be right, but short term that doesn't help us as we're doing index based personalization of servers, which means we want index->server relationships to be unique (e.g rebuilding index "0" and getting a completely different node in the rack built will not be acceptable for some operators).

Another possibility is we stop using heat to build the servers altogether and instead build them via a mistral workflow, but again that is a long term idea. For now I'll hack around it with some ugly yaql logic :\

Revision history for this message
Steven Hardy (shardy) wrote :

For anyone interested in the workaround, it looks like this:

        first_hostname_in_group:
          yaql:
            expression: coalesce($.data, []).first(null)
            data: {get_attr: [TheResourceGroup, hostname]}

hostname returns a list, which may be empty for zero count ResourceGroups, hence the first(null). The coalesce is needed because get_attr returns None during validation, which breaks the query unless we handle it by defaulting to an empty list.

Rabi Mishra (rabi)
Changed in heat:
milestone: ocata-1 → ocata-2
Rabi Mishra (rabi)
Changed in heat:
milestone: ocata-2 → ocata-3
Revision history for this message
Thomas Herve (therve) wrote :

We don't really have a great solution for now, I suspect it relies on improving validation in general. There is a workaround, so let's push it for now.

Changed in heat:
milestone: ocata-3 → next
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.