TemplateResource RefId is wrong

Bug #1381136 reported by Mike Spreitzer
12
This bug affects 1 person
Affects Status Importance Assigned to Milestone
OpenStack Heat
Fix Released
Medium
Zane Bitter

Bug Description

The hot incantation "{get_resource: foo}" returns an AWS ARN when foo is a stack. Other resource types have parameters whose value should be the UUID of a resource. Such a value is not available to a template author that wants to refer to a resource that happens to be a stack.

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

The return value of get_resource depends on the resource implementation, what resource type is "foo" in this case?

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

The cases I noticed are when "foo" is an AWS::CloudFormation::Stack or what used to be called a provider resource (I think it might be called a "template resource" now).

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

Maybe the original description of this bug was not clear. The problem concerns the interaction of two resources, let us call them A and B. The problem happens when a property of B is supposed to be given a value that is the ID of a resource (such as A); if A is a stack then the template author can not write "{get_resource: A}" as the value of the B property in question, because {get_resource: A} does not return a resource ID in this case.

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

Mike: If you're talking about the AWS stack resource, then returning an ARN is not unexpected:

http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html

Like I said, what get_resource (equivalent to "Ref" in CFN templates) returns is dependent on the resource, not the template DSL you use so there is no "hot inantation" of an AWS resource.

So what I think you are saying is that there's a bug in provider resources (which are *not* AWS Stack resources), e.g template resource GetRefId has a bug here:

https://github.com/openstack/heat/blob/master/heat/engine/resources/template_resource.py#L270

That is a bug, this (in the AWS Stack resource) is not:

https://github.com/openstack/heat/blob/master/heat/engine/resources/stack.py#L95

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

Sorry, quoting with typos, need more coffee, I meant incantation there obviously ;)

summary: - Nested stacks have unexpected IDs
+ TemplateResource RefId is wrong
Changed in heat:
status: New → Confirmed
importance: Undecided → Medium
assignee: nobody → Steven Hardy (shardy)
milestone: none → kilo-1
Revision history for this message
Steven Hardy (shardy) wrote :

btw - if for future reports you're able to provide a reproducer template that would be great, as it's generally a quicker way to understand the issue someone is having than abstract discussions about resource interactions.

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

Having discussed this with asalkeld, it seems it was a deliberate choice to make TemplateResource return an ARN, otherwise heat resource-show won't work on the provider resource.

Maybe there's some way we can resolve that, as I do think, if possible, it'd be better for get_resource to return the stack ID by default, for native OS:: resources.

Mike - it sounds like this is preventing you from doing something, but you haven't stated what, so can you please provide a concrete use-case for this, ideally a template you'd like to work but doesn't?

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

My original vision of TemplateResource was to allow the user to specify a special Output in their template to specify the resource ID (this would allow a TemplateResource to properly stand in for some other resource type in a template).

Whether or not we think that's a good idea, it's pretty clear to me that anything that isn't an AWS:: resource should *never* return an ARN.

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

Zane, regarding the first part of comment #8: was your vision that a template might output a resource ID that is the resource ID of one of the resources it contains, or a resource ID that the template synthesizes (e.g., by string munging or random string generation)? I would be surprised by a system that has the same resource ID on two different resources (e.g., a stack and also a resource contained in that stack).

This connects to the bigger picture here, which I now see I did not describe clearly enough at the beginning. The problem is not that I am personally surprised by the output of {get_resource: somestack}. The problem is that a template author has no way to refer to a stack, in places where reference is done by resource ID. The first place I noticed this is for OS::Heat::HARestarter, which takes a resource ID for the resource that is the head of sub-graph to delete and re-create. The second place this has come up is in the proposal to add a list of members-to-delete to as an optional property of a scaling group; part of the design problem there is to decide how the members to be deleted should be identified.

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

Sorry, that was maybe a little too sloppy. The problem is that a template author has no way to refer to a resource that is a nested stack, in places where reference is done by resource ID.

Concrete example 1:

resources:
  somestack:
    type: AWS::CloudFormation::Stack
    properties: {...stuff...}

  replacer:
    type: OS::Heat::HARestarter
    properties:
      InstanceID: {get_resource: somestack}

That does not work.

Concrete example 2:

resources:
  sg:
    type: OS::Heat::ResourceGroup
    properties:
      resource_def:
        type: Something.yaml
        properties: ...
      removal_policy:
        resource_id_list: [ ... the result of FnGetRefId of a member ... ]

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

> InstanceID: {get_resource: somestack}

Why would you ever expect this to work, given that somestack returns a unique reference (not necessarily the resource ID) to a stack, not an instance?

> resource_id_list: [ ... the result of FnGetRefId of a member

This will work, in fact it already does in the patch I posted.

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

> My original vision of TemplateResource was to allow the user to specify a special Output in their template to specify the resource ID

+100 - stevebaker and I were discussing this in the context of provider-resource abstracted SoftwareConfig resources recently, and IMO it's something we do need.

I don't think it's "same resource ID on two different resources" at all, merely giving some control to template authors who want to use provider resources for encapulation transparently. The resource has exactly one ID, as does the stack, you're just changing what get_resource references for template-author convenience.

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

> was your vision that a template might output a resource ID that is the resource ID of one of the resources it contains, or a resource ID that the template synthesizes (e.g., by string munging or random string generation)?

I figured it would be an output, so the user could in principle do whatever they like, but the most common case would be to reference a resource ID from within the nested template. So e.g. you could specify in your environment file a mapping from OS::Nova::Server -> my_customised_server.yaml where you customise the server to e.g. add a port, or preset some common properties, or something. You'd then be able to use OS::Nova::Server in _exactly_ the same way as if you had not mapped it, because when you do {get_resource: } on it it would still return the physical resource ID of the server.

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

Re concrete example 1: HARestarter can delete a nested stack. It can delete any kind of resource. Sometimes I actually want it to delete a nested stack.

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

No design decision should ever be made on the basis of what's best for HARestarter.

That said, I don't see why your example #1 wouldn't work, unless another resource in the parent stack had the same ID.

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

While developing patch set 4 of https://review.openstack.org/#/c/127884/ , I tested the equivalent of concrete example 1 (you do not see the equivalent of concrete example 1 in patch set 3 because I did not get to the equivalent of concrete example 1 until after I had already made other changes; you do not see the equivalent of concrete example 1 in patch set 4, since I found that it does not work ). The HARestarter was not finding "thing" (which is a nested stack, created using the AWS resource type for stacks). HARestarter looks for a resource based on resource ID, but the get_resource intrinsic returns the refid.

For a nested stack resource, the refid and the resource ID are different --- the former is an ARN and the latter is not.

The bug I am trying to report is that this difference causes grief.

There are several ways it could be fixed, even while retaining the fact that the refid of an AWS::CloudFormation::Stack is an ARN. One would be to introduce an alternative to get_resource that returns the resource ID instead of the refid. Another would be to make sure that every resource property that is intended to be able to refer to a nested stack (perhaps among other types) is defined to take a refid instead of a resource ID. Note that a constraint on every fubar is trivially satisfied if there are no fubars.

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

My concern is not for HARestarter but for users that want health maintenance. As you see, I have found a way to get it despite this bug. If you want to leave HARestarter uniquely screwed, that is OK with me if you find the workaround in https://review.openstack.org/#/c/127884/ to be acceptable.

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

Part of my concern here is that I realized that Heat has some sharp edges. Do we really want these sharp edges? I have just done some language lawyering, and here is what I have realized.

In the Template Guide --- which is found under Python Developer documentation but acknowledged to also be relevant to users --- the section about resources (http://docs.openstack.org/developer/heat/template_guide/hot_spec.html#resources-section) consistently uses the term "resource ID" for what I have been calling "resource name". I'll take that as a correction of my terminology. The Template Guide also has a definition of the get_resource intrinsic (http://docs.openstack.org/developer/heat/template_guide/hot_spec.html#get-resource), and it consistently uses the term "resource ID" for that function's input and uses the term "reference ID" for that function's output.

Python developers see that a Resource has an "id", and fall into the habit of saying "resource ID" when we mean that field. I am not the only one who has done this; in comment #8 here, Zane followed my lead in this direction.

Of course, Resource.id does not hold what the Template Guide defines to be the resource's ID. It is actually the resource's reference ID in many cases but not all.

It is fast to look up a Resource by it's Resource.id (that being the primary key). For a general given resource reference ID, there is no general way to look up the reference except by enumerating the resources of the stack (presuming the relevant stack is already known) and comparing reference IDs. Are we even guaranteed uniqueness?

Revision history for this message
Steve Baker (steve-stevebaker) wrote : Re: [Bug 1381136] Re: TemplateResource RefId is wrong

On 19/10/14 10:47, Mike Spreitzer wrote:
> Part of my concern here is that I realized that Heat has some sharp
> edges. Do we really want these sharp edges? I have just done some
> language lawyering, and here is what I have realized.
>
> In the Template Guide --- which is found under Python Developer
> documentation but acknowledged to also be relevant to users --- the
> section about resources
> (http://docs.openstack.org/developer/heat/template_guide/hot_spec.html
> #resources-section) consistently uses the term "resource ID" for what I
> have been calling "resource name". I'll take that as a correction of my
> terminology. The Template Guide also has a definition of the
> get_resource intrinsic
> (http://docs.openstack.org/developer/heat/template_guide/hot_spec.html
> #get-resource), and it consistently uses the term "resource ID" for that
> function's input and uses the term "reference ID" for that function's
> output.
Were in the process of writing the end-user focused template writing guide:
http://git.openstack.org/cgit/openstack/openstack-manuals/tree/doc/hot-guide/source

Feel free to submit reviews for semantic clarifications there. Until the
new hot-guide is published I think we should write all new content in
the openstack-manuals repo and periodically sync back to the developer
template_guide (which will eventually be deleted).

Personally I'd like the spec to change <resource ID> to <resource name>
and for it to state somewhere that resource names are unique within a
stack. We already use <resource name> in other documentation artifacts:

$ heat help resource-show
usage: heat resource-show <NAME or ID> <RESOURCE>

Describe the resource.

Positional arguments:
   <NAME or ID> Name or ID of stack to show the resource for.
   <RESOURCE> Name of the resource to show the details for.

> Python developers see that a Resource has an "id", and fall into the
> habit of saying "resource ID" when we mean that field. I am not the
> only one who has done this; in comment #8 here, Zane followed my lead in
> this direction.
>
> Of course, Resource.id does not hold what the Template Guide defines to
> be the resource's ID. It is actually the resource's reference ID in
> many cases but not all.
>
> It is fast to look up a Resource by it's Resource.id (that being the
> primary key). For a general given resource reference ID, there is no
> general way to look up the reference except by enumerating the resources
> of the stack (presuming the relevant stack is already known) and
> comparing reference IDs. Are we even guaranteed uniqueness?
>
Developer semantics don't map at all to user semantics, so when you
submit your hot-guide changes make sure you make no reference to
Resource.id.

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

I agree with switching the terminology to "resource name" from what the Template Guide defines as "resource ID". I think there are two good reasons for this. One is that "resource name" is a more natural term for this concept. They are used like what are called names in many languages and formalisms. And witness the fact that we all use this term anyway. Another is that "resource ID" is problematic. Like it or not, anyone who looks at the source sees the class named Resource and sees that it has a field named "id". Of course users do not have to know everything developers do, but having users use a term that is confusing to developers adds an unnecessary degree of difficulty.

Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

The issue of whether to use the term "resource name" or "resource ID" is not actually where this bug started. This bug was opened because OS::Heat::HARestarter consumes an identifier that is not always what the get_resource intrinsic function produces and is not accessible in another way. Maybe there are other resource types besides HARestarter that also have this problem, I am not sure. The simplest way to fix this would be to change such consuming resource types to consume a resource reference ID (i.e., what get_resource produces) instead of what they do today. Another way to fix it would be to introduce something a template author could write that produces what the consumer expects, for all types of referenced resource; I favor that less because it exposes an additional concept to template authors.

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

> HARestarter looks for a resource based on resource ID, but the get_resource intrinsic returns the refid.

Ah, you're quite right. Sorry, my mistake.

This is a straight up bug in HARestarter. Instead of self._find_resource() it should be calling self.stack.resource_by_refid(). Yet another reason that this unmaintained craziness should have been defenestrated years ago.

Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to heat (master)

Fix proposed to branch: master
Review: https://review.openstack.org/129981

Changed in heat:
assignee: Steven Hardy (shardy) → Zane Bitter (zaneb)
status: Confirmed → In Progress
Revision history for this message
Mike Spreitzer (mike-spreitzer) wrote :

The discussion here has wandered through another topic, about terminology used in the documentation. I am not sure whether to incorporate that issue in this bug or open a distinct bug for it.

Revision history for this message
Steve Baker (steve-stevebaker) wrote : Re: [Bug 1381136] Re: TemplateResource RefId is wrong

On 22/10/14 06:26, Mike Spreitzer wrote:
> The discussion here has wandered through another topic, about
> terminology used in the documentation. I am not sure whether to
> incorporate that issue in this bug or open a distinct bug for it.
>
Could you raise a bug here for the hot-guide?

https://bugs.launchpad.net/openstack-manuals/+filebug

Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to heat (master)

Reviewed: https://review.openstack.org/129981
Committed: https://git.openstack.org/cgit/openstack/heat/commit/?id=c4dd7d70b5d112200b8491f38f491c06a4c17643
Submitter: Jenkins
Branch: master

commit c4dd7d70b5d112200b8491f38f491c06a4c17643
Author: Zane Bitter <email address hidden>
Date: Tue Oct 21 13:04:52 2014 -0400

    Make HARestarter do a proper lookup of the RefID

    HARestarter is a primitive prototype that is barely maintained. Its
    implementation still dates to the era when the resource name, physical
    resource ID and RefId were regularly used interchangably.

    This change substitutes Stack.resource_by_refid() for the previous
    (incorrect) home-grown hack, so that at least the giant red flags will be
    easy to grep for.

    Change-Id: I9d81dfcd5d34282c8bd83bbd98350e75c1ec0eb2
    Closes-Bug: #1381136

Changed in heat:
status: In Progress → Fix Committed
Thierry Carrez (ttx)
Changed in heat:
status: Fix Committed → Fix Released
Thierry Carrez (ttx)
Changed in heat:
milestone: kilo-1 → 2015.1.0
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.