Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup Empty AutoAliasing Objects #1064

Merged
merged 2 commits into from
May 2, 2023
Merged

Conversation

iwahbe
Copy link
Member

@iwahbe iwahbe commented May 1, 2023

This PR modifies token mapping to not add extra fields for otherwise empty objects. This is necessary because AutoName sets a full tfbridge.SchemaInfo, it does not modify one.

@iwahbe iwahbe self-assigned this May 1, 2023
@github-actions
Copy link

github-actions bot commented May 1, 2023

Diff for pulumi-azuread with merge commit 16a4ff2

@github-actions
Copy link

github-actions bot commented May 1, 2023

Diff for pulumi-random with merge commit 16a4ff2

iwahbe added a commit to pulumi/pulumi-docker that referenced this pull request May 1, 2023
@github-actions
Copy link

github-actions bot commented May 1, 2023

Diff for pulumi-gcp with merge commit 16a4ff2

@github-actions
Copy link

github-actions bot commented May 1, 2023

Diff for pulumi-azure with merge commit 16a4ff2

@t0yv0
Copy link
Member

t0yv0 commented May 1, 2023

How does this connect to the user problem prompting this PR, would it be possible to elaborate? The tests are at a level of indirection, no elucidating new tests are added, and it's not obvious how the problem is being fixed.

I believe you will recover old behavior by putting p.SetAutonaming before the call to x.AutoAliasing.

After this PR do we believe that the order of p.SetAutonaming and x.AutoAliasing does not matter anymore?

Does editing the existing test not weaken the MaxItems one test strength?

I'm going to be able to review tomorrow morning but it's not an obvious fix to review in a tired state.

Copy link
Contributor

@guineveresaenger guineveresaenger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like some comments that describe the recursion pattern, and the purpose of each inline function.
Can we also link the Docker PR that failed, with an explanation of why that happened?

Thank you for the quick turnaround.

pkg/tfbridge/x/token_test.go Show resolved Hide resolved
}

var walk func(*fieldHistory, *b.SchemaInfo, shim.Schema)
walk = func(h *fieldHistory, info *b.SchemaInfo, schema shim.Schema) {
walk = func(h *fieldHistory, info *b.SchemaInfo, schema shim.Schema) (hasH bool, hasI bool) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is a lot of state context here that gets confusing because the variable names are so similar.
For example, we return hasH and hasI here but on line 667 we assign them to keepH and keepI and it would be great to know what is prompting us to "keep" info or history.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added that comment.

f(k, v)
h, hasH := getNonNil(hist, k)
i, hasI := getNonNil(info, k)
keepH, keepI := walk(h, i, v)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what is being kept here.

Should we keep history/info?
Are we checking whether history or info are being kept?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should keep it when (1) it already existed or (2) we stored useful information in it. I added some comments explaining what we are trying to do that will hopefully clarify.

pkg/tfbridge/x/tokens.go Show resolved Hide resolved
pkg/tfbridge/x/tokens.go Show resolved Hide resolved
pkg/tfbridge/x/tokens.go Show resolved Hide resolved
@github-actions
Copy link

github-actions bot commented May 1, 2023

Diff for pulumi-azuread with merge commit dd58726

@github-actions
Copy link

github-actions bot commented May 1, 2023

Diff for pulumi-random with merge commit dd58726

@github-actions
Copy link

github-actions bot commented May 1, 2023

Diff for pulumi-gcp with merge commit dd58726

@github-actions
Copy link

github-actions bot commented May 1, 2023

Diff for pulumi-azure with merge commit dd58726

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azuread with merge commit 1a05aa0

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-random with merge commit 1a05aa0

@iwahbe iwahbe force-pushed the iwahbe/auto-aliasing-cleanup branch from 5a895da to ecab2c4 Compare May 2, 2023 00:11
@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azuread with merge commit 4c501ad

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azuread with merge commit 5ea397d

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-random with merge commit 4c501ad

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-random with merge commit 5ea397d

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-gcp with merge commit 1a05aa0

@iwahbe
Copy link
Member Author

iwahbe commented May 2, 2023

How does this connect to the user problem prompting this PR, would it be possible to elaborate? The tests are at a level of indirection, no elucidating new tests are added, and it's not obvious how the problem is being fixed.

I believe you will recover old behavior by putting p.SetAutonaming before the call to x.AutoAliasing.

After this PR do we believe that the order of p.SetAutonaming and x.AutoAliasing does not matter anymore?

Does editing the existing test not weaken the MaxItems one test strength?

I'm going to be able to review tomorrow morning but it's not an obvious fix to review in a tired state.

After this PR we do believe that p.SetAutonaming and x.AutoAliasing should be callable in any order.1 We want this property to avoid confusion.

The test was more specific than necessary. Specifically, it was testing for a property that was not necessary for the desired behavior that we want to change:

- assert.Nil(t, info.Resources["pkg_r1"].Fields["f2"].MaxItemsOne)
+ assert.Nil(t, info.Resources["pkg_r1"].Fields["f2"])

Previously, info.Resources["pkg_r1"].Fields["f2"] was equal to &tfbridge.SchemaInfo{}, and we only cared that info.Resources["pkg_r1"].Fields["f2"].MaxItemsOne was nil. We are tightening the requirements to ensure that the full thing is nil.

What we actually cared about is this property (expressed in TS style pseudo-code):

info?.Resources?["pkg_r1"]?.Fields?["f2"]?.MaxItemsOne == nil

Because of how painful it is to express this in go, I abbreviated to asserting MaxItemsOne was nil.

Footnotes

  1. I believe that SetAutonaming will break at runtime when it is applied to a non-string field, so I'm discounting the possibility of a list type with auto-naming called name.

Comment on lines 750 to 754
// (*ProviderInfo).SetAutonaming only applies to fields that are not present in their
// resource's property map. We need to make sure that unless we mark a field as
// `MaxItemsOne: nonNil` for some non-nil value, we don't leave that field entry behind
// since that will disable SetAutonaming.
func TestMaxItemsOneAliasingWithAutoNaming(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guineveresaenger @t0yv0 Sorry for the confusing PR. I have added our motivating example as a test case with an explanation of the underlying logic for the change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brilliant. Oof, so SetAutonaming does look at whether the SchemaInfo is present or no.

Saw this code:

				if _, hasfield := res.Fields[nameProperty]; !hasfield {
					if res.Fields == nil {
						res.Fields = make(map[string]*SchemaInfo)
					}
					res.Fields[nameProperty] = AutoName(nameProperty, maxLength, separator)
				}

I would rephrase

(*ProviderInfo).SetAutonaming only applies to fields that are not present in their
// resource's property map.

With

(*ProviderInfo).SetAutonaming skips fields that have a SchemaInfo already defined in ResourceInfo.Fields

I always confuse the Info things with he provider maps from shim.SchemaMap.

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azure with merge commit 1a05aa0

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-gcp with merge commit 4c501ad

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-gcp with merge commit 5ea397d

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azure with merge commit 4c501ad

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azure with merge commit 5ea397d

@iwahbe iwahbe force-pushed the iwahbe/auto-aliasing-cleanup branch from ecab2c4 to 2b93875 Compare May 2, 2023 00:35
@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azuread with merge commit 78dbc7b

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-random with merge commit 78dbc7b

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-gcp with merge commit 78dbc7b

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azure with merge commit 78dbc7b

@t0yv0
Copy link
Member

t0yv0 commented May 2, 2023

Because of how painful it is to express this in go, I abbreviated to asserting MaxItemsOne was nil.

Yes that's true. Yes. I think we try not to care anywhere about the different flavors of "missing", not to attach semantics to nil vs missing key here, so what could work is getter functions that isolate the caller from nils, like this:

assert.Nil(t, info.Resource("pkg_r1").Field("f2").MaxItemsOne)

But perhaps for another day.

pkg/tfbridge/x/tokens.go Outdated Show resolved Hide resolved
@t0yv0
Copy link
Member

t0yv0 commented May 2, 2023

Well this is interesting, it works around the immediate problem but looks a tad error prone. I'm a bit worried about this quirk we found in SetAutonaming behavior, and perhaps there's still conditions where the order of application matters.

Consider this:

  • autoaliasing runs and injects a MaxItems=1 specification, creating a SchemaInfo in ResourceInfo.Fields
  • then autonaming runs and finds that whoops, the user set ResourceInfo.Fields["spock"] so I'm going to skip it

To the end user this looks like we accidentally disabled auto naming.

Could we do better? Could we enforce the order so SetAutonaming is always before aliasing?

Copy link
Contributor

@jazzyfresh jazzyfresh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, especially with the new test

@iwahbe iwahbe force-pushed the iwahbe/auto-aliasing-cleanup branch from 2b93875 to 7747fa1 Compare May 2, 2023 21:34
@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-random with merge commit 07fcd2f

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azuread with merge commit 07fcd2f

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-gcp with merge commit 07fcd2f

@iwahbe
Copy link
Member Author

iwahbe commented May 2, 2023

Well this is interesting, it works around the immediate problem but looks a tad error prone. I'm a bit worried about this quirk we found in SetAutonaming behavior, and perhaps there's still conditions where the order of application matters.

Unfortunately, I think the quirk is here to stay. I've seen plenty of tk: { Fields: map[string]*tfbridge.SchemaInfo{ "name": {Name: "name" } } }. AFAIK, this exists only to disable auto-naming.

AutoNaming should have been more selective by checking if *SchemaInfo.Defaults was nil instead of *SchemaInfo, but I think that change needs to wait for bridge v4.0.0.

Consider this:

  • autoaliasing runs and injects a MaxItems=1 specification, creating a SchemaInfo in ResourceInfo.Fields
  • then autonaming runs and finds that whoops, the user set ResourceInfo.Fields["spock"] so I'm going to skip it

To the end user this looks like we accidentally disabled auto naming.

If AutoAliasing saw a resource and injected ResourceInfo["spock"].MaxItemsOne = True(), then SetAutonames would not be affected, since it only effects fields called "name".

If AutoAliasing saw a resource and injected ResourceInfo["name"].MaxItemsOne = True(), it would imply that ResourceMap.Get(resourceName).Schema().Get("name").Type is either a List, Map or Set (something that MaxItemsOne makes sense on). If that is the case, then SetAutonaming would be invalid, since it assumes that the name field is of type String.

The end user will never observe AutoAliasing disabling a valid auto name.

Could we do better? Could we enforce the order so SetAutonaming is always before aliasing?

We could enforce the ordering, but I don't think we should.

  1. We impose accidental complexity on our users. Since we can't order enforce in the type system, this is a runtime panic when developing a provider. We should avoid this where possible.
  2. This cuts down the size of bridge-metadata.json to only keep the data it needs. This makes diffs much more meaningful.

@github-actions
Copy link

github-actions bot commented May 2, 2023

Diff for pulumi-azure with merge commit 07fcd2f

@t0yv0
Copy link
Member

t0yv0 commented May 2, 2023

Brilliant, so the cases don't overlap based on type. Autonaming is interested in name type=string and maxitems=1 aliasing is looking at type=list[x] or type=set[x]. That's great.

AutoNaming should have been more selective by checking if *SchemaInfo.Defaults was nil instead of *SchemaInfo, but I think that change needs to wait for bridge v4.0.0.

I like that. Care to backlog and label say impact/breaking? We can then find all those things when contemplating 4.0.

@t0yv0 t0yv0 self-requested a review May 2, 2023 22:31
Copy link
Contributor

@guineveresaenger guineveresaenger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for the extra comments and improved varnames! 💟

@iwahbe
Copy link
Member Author

iwahbe commented May 2, 2023

Brilliant, so the cases don't overlap based on type. Autonaming is interested in name type=string and maxitems=1 aliasing is looking at type=list[x] or type=set[x]. That's great.

AutoNaming should have been more selective by checking if *SchemaInfo.Defaults was nil instead of *SchemaInfo, but I think that change needs to wait for bridge v4.0.0.

I like that. Care to backlog and label say impact/breaking? We can then find all those things when contemplating 4.0.

Follow up issue is #1069.

@iwahbe iwahbe merged commit 753c829 into master May 2, 2023
8 checks passed
@iwahbe iwahbe deleted the iwahbe/auto-aliasing-cleanup branch May 2, 2023 23:02
iwahbe added a commit to pulumi/pulumi-docker that referenced this pull request May 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants