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
[sdk/go] Ensure Assets of AssetArchive are non-nil when creating and deserializing #14007
Conversation
Changelog[uncommitted] (2023-09-22)Bug Fixes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should do a similar fix for Asset
sdk/go/common/resource/asset_test.go
Outdated
|
||
emptyArchive, err := NewAssetArchive(nil) | ||
assert.True(t, emptyArchive.IsAssets(), "even empty archives should be have empty assets") | ||
assert.NoError(t, err, "Creating an empty archive should work") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A) Do the err check first
B) Use require.NoError, generally if we have an error the other asserts will just end up panic'ing (due to like nil access exceptions and the like)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅
sdk/go/common/resource/asset.go
Outdated
@@ -577,6 +582,10 @@ func (a *Archive) Serialize() map[string]interface{} { | |||
} | |||
} | |||
result[ArchiveAssetsProperty] = assets | |||
} else { | |||
// Ensure that the assets property is always present, even if empty. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The JSON/YAML attributes have omitempty so this would just get dropped anyway. But that's expected we only want the field when this is an asset archive, and if assets is nil then it isn't. i.e. just remove this block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't notice those since we are dealing with a custom serialization/deserialization here but indeed, this seems redundant so removed this block
sdk/go/common/resource/asset.go
Outdated
if !ok { | ||
return &Archive{}, false, fmt.Errorf("unexpected archive contents of type %T", v) | ||
} | ||
assets := make(map[string]interface{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this is safe? Looks like we could create an Archive with assets and path set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the DeserializeArchive
method such that it is not possible to construct conflicting fields:
- When we check for the
path
property and it exists, we immediately returnNewPathArchive
- When we check for the
uri
property and it exists, we immediately returnNewURIArchive
- Finally if we didn't find
path
noruri
, we get theassets
and default to an empty map
At the start of the function, we check that the input object must have one of path
, uri
or assets
Edit: no longer using New{...}Archive
functions, because they recompute the hash, instead just constructing the archive using the deserialized values
a31308e
to
936d415
Compare
173898a
to
320ccd5
Compare
b689485
to
cd259a1
Compare
sdk/go/common/resource/asset.go
Outdated
a := &Archive{Sig: ArchiveSig, URI: uri} | ||
err := a.EnsureHash() | ||
return a, err | ||
} | ||
|
||
func (a *Archive) IsAssets() bool { return a.Assets != nil } | ||
func (a *Archive) IsAssets() bool { return !a.IsPath() && !a.IsURI() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should just be a.Assets != nil. Whenever we construct an Archive object we'll ensure it's a non-nil map.
21d4297
to
662301d
Compare
<!--- Thanks so much for your contribution! If this is your first time contributing, please ensure that you have read the [CONTRIBUTING](https://github.com/pulumi/pulumi/blob/master/CONTRIBUTING.md) documentation. --> # Description <!--- Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. --> Fixes #15729. This fixes Assets and Archives to allow four states, as opposed to the three that #14007 had enforced. An asset can either be Text, Path, Uri, or none. That is `IsText`, `IsPath`, and `IsURI` can all return false. Similarly for archives except with Assets instead of Text. This happens when a provider returns an Assert (or Archive) with a hash value set, but no other contents. The Asset and Archive objects have been updated to handle this case, and a number of places in the CLI that asserted that one of IsText/IsPath/IsURI were true have been fixed up to handle the case of all three being false. ## Checklist - [x] I have run `make tidy` to update any new dependencies - [x] I have run `make lint` to verify my code passes the lint check - [x] I have formatted my code using `gofumpt` <!--- Please provide details if the checkbox below is to be left unchecked. --> - [x] I have added tests that prove my fix is effective or that my feature works <!--- User-facing changes require a CHANGELOG entry. --> - [x] I have run `make changelog` and committed the `changelog/pending/<file>` documenting my change <!-- If the change(s) in this PR is a modification of an existing call to the Pulumi Cloud, then the service should honor older versions of the CLI where this change would not exist. You must then bump the API version in /pkg/backend/httpstate/client/api.go, as well as add it to the service. --> - [ ] Yes, there are changes in this PR that warrants bumping the Pulumi Cloud API version <!-- @pulumi employees: If yes, you must submit corresponding changes in the service repo. -->
Fixes #11103
The problem in the issue the distinction between
Assets
or an archive beingnil
vs. being an empty map of assets. When creating and deserializing Archives,nil
was allowed which leads to panics when assertingarchive.IsAssets()
because theAssets
isnil
even though it is a proper archive.This PR fixes the issue by ensuring that an instance of
Archive
will have a non-nilAssets
field whether that is during construction or marshalling.Checklist
make tidy
to update any new dependenciesmake lint
to verify my code passes the lint checkgofumpt
make changelog
and committed thechangelog/pending/<file>
documenting my change