2021-09-13 16:05:31 +00:00
|
|
|
// Copyright 2016-2021, Pulumi Corporation.
|
2018-05-22 19:43:36 +00:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2017-02-20 19:18:47 +00:00
|
|
|
|
Overhaul resources, planning, and environments
This change, part of pulumi/lumi#90, overhauls quite a bit of the
core resource, planning, environments, and related areas.
The biggest amount of movement comes from the splitting of pkg/resource
into multiple sub-packages. This results in:
- pkg/resource: just the core resource data structures.
- pkg/resource/deployment: all planning and deployment logic.
- pkg/resource/environment: all environment, configuration, and
serialized checkpoint structures and logic.
- pkg/resource/plugin: all dynamically loaded analyzer and
provider logic, including the actual loading and RPC mechanisms.
This also splits the resource abstraction up. We now have:
- resource.Resource: a shared interface.
- resource.Object: a resource that is connected to a live object
that will periodically observe mutations due to ongoing
evaluation of computations. Snapshots of its state may be
taken; however, this is purely a "pre-planning" abstraction.
- resource.State: a snapshot of a resource's state that is frozen.
In other words, it is no longer connected to a live object.
This is what will store provider outputs (ID and properties),
and is what may be serialized into a deployment record.
The branch is in a half-baked state as of this change; more changes
are to come...
2017-06-08 23:37:40 +00:00
|
|
|
package plugin
|
2017-02-20 19:18:47 +00:00
|
|
|
|
|
|
|
import (
|
2021-09-10 20:18:08 +00:00
|
|
|
"fmt"
|
2017-02-20 19:18:47 +00:00
|
|
|
"reflect"
|
|
|
|
"sort"
|
|
|
|
|
2017-09-14 23:40:44 +00:00
|
|
|
"github.com/pkg/errors"
|
2024-01-17 09:35:20 +00:00
|
|
|
"google.golang.org/protobuf/types/known/structpb"
|
2017-02-20 19:18:47 +00:00
|
|
|
|
2021-03-17 13:20:05 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/archive"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/asset"
|
2021-03-17 13:20:05 +00:00
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
|
|
|
|
"github.com/pulumi/pulumi/sdk/v3/go/common/util/logging"
|
2017-02-20 19:18:47 +00:00
|
|
|
)
|
|
|
|
|
2017-02-24 23:41:56 +00:00
|
|
|
// MarshalOptions controls the marshaling of RPC structures.
|
|
|
|
type MarshalOptions struct {
|
2024-02-02 11:09:58 +00:00
|
|
|
Label string // an optional label for debugging.
|
|
|
|
SkipNulls bool // true to skip nulls altogether in the resulting map.
|
|
|
|
KeepUnknowns bool // true if we are keeping unknown values (otherwise we skip them).
|
|
|
|
RejectUnknowns bool // true if we should return errors on unknown values. Takes precedence over KeepUnknowns.
|
|
|
|
ElideAssetContents bool // true if we are eliding the contents of assets.
|
|
|
|
ComputeAssetHashes bool // true if we are computing missing asset hashes on the fly.
|
|
|
|
KeepSecrets bool // true if we are keeping secrets (otherwise we replace them with their underlying value).
|
|
|
|
RejectAssets bool // true if we should return errors on Asset and Archive values.
|
|
|
|
KeepResources bool // true if we are keeping resoures (otherwise we return raw urn).
|
|
|
|
SkipInternalKeys bool // true to skip internal property keys (keys that start with "__") in the resulting map.
|
|
|
|
KeepOutputValues bool // true if we are keeping output values.
|
|
|
|
UpgradeToOutputValues bool // true if secrets and unknowns should be upgraded to output values.
|
2024-05-02 11:32:54 +00:00
|
|
|
WorkingDirectory string // the optional working directory to use when serializing assets & archives.
|
2017-02-24 23:41:56 +00:00
|
|
|
}
|
|
|
|
|
2017-07-20 16:06:39 +00:00
|
|
|
const (
|
|
|
|
// UnknownBoolValue is a sentinel indicating that a bool property's value is not known, because it depends on
|
|
|
|
// a computation with values whose values themselves are not yet known (e.g., dependent upon an output property).
|
|
|
|
UnknownBoolValue = "1c4a061d-8072-4f0a-a4cb-0ff528b18fe7"
|
|
|
|
// UnknownNumberValue is a sentinel indicating that a number property's value is not known, because it depends on
|
|
|
|
// a computation with values whose values themselves are not yet known (e.g., dependent upon an output property).
|
|
|
|
UnknownNumberValue = "3eeb2bf0-c639-47a8-9e75-3b44932eb421"
|
|
|
|
// UnknownStringValue is a sentinel indicating that a string property's value is not known, because it depends on
|
|
|
|
// a computation with values whose values themselves are not yet known (e.g., dependent upon an output property).
|
|
|
|
UnknownStringValue = "04da6b54-80e4-46f7-96ec-b56ff0331ba9"
|
|
|
|
// UnknownArrayValue is a sentinel indicating that an array property's value is not known, because it depends on
|
|
|
|
// a computation with values whose values themselves are not yet known (e.g., dependent upon an output property).
|
|
|
|
UnknownArrayValue = "6a19a0b0-7e62-4c92-b797-7f8e31da9cc2"
|
|
|
|
// UnknownAssetValue is a sentinel indicating that an asset property's value is not known, because it depends on
|
|
|
|
// a computation with values whose values themselves are not yet known (e.g., dependent upon an output property).
|
|
|
|
UnknownAssetValue = "030794c1-ac77-496b-92df-f27374a8bd58"
|
|
|
|
// UnknownArchiveValue is a sentinel indicating that an archive property's value is not known, because it depends
|
|
|
|
// on a computation with values whose values themselves are not yet known (e.g., dependent upon an output property).
|
|
|
|
UnknownArchiveValue = "e48ece36-62e2-4504-bad9-02848725956a"
|
|
|
|
// UnknownObjectValue is a sentinel indicating that an archive property's value is not known, because it depends
|
|
|
|
// on a computation with values whose values themselves are not yet known (e.g., dependent upon an output property).
|
|
|
|
UnknownObjectValue = "dd056dcd-154b-4c76-9bd3-c8f88648b5ff"
|
|
|
|
)
|
|
|
|
|
|
|
|
// MarshalProperties marshals a resource's property map as a "JSON-like" protobuf structure.
|
2017-09-14 23:40:44 +00:00
|
|
|
func MarshalProperties(props resource.PropertyMap, opts MarshalOptions) (*structpb.Struct, error) {
|
2017-07-20 16:06:39 +00:00
|
|
|
fields := make(map[string]*structpb.Value)
|
Make more progress on the new deployment model
This change restructures a lot more pertaining to deployments, snapshots,
environments, and the like.
The most notable change is that the notion of a deploy.Source is introduced,
which splits the responsibility between the deploy.Plan -- which simply
understands how to compute and carry out deployment plans -- and the idea
of something that can produce new objects on-demand during deployment.
The primary such implementation is evalSource, which encapsulates an
interpreter and takes a package, args, and config map, and proceeds to run
the interpreter in a distinct goroutine. It synchronizes as needed to
poke and prod the interpreter along its path to create new resource objects.
There are two other sources, however. First, a nullSource, which simply
refuses to create new objects. This can be handy when writing isolated
tests but is also used to simulate the "empty" environment as necessary to
do a complete teardown of the target environment. Second, a fixedSource,
which takes a pre-computed array of objects, and hands those, in order, to
the planning engine; this is mostly useful as a testing technique.
Boatloads of code is now changed and updated in the various CLI commands.
This further chugs along towards pulumi/lumi#90. The end is in sight.
2017-06-10 18:50:47 +00:00
|
|
|
for _, key := range props.StableKeys() {
|
2017-07-01 18:51:52 +00:00
|
|
|
v := props[key]
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(9).Infof("Marshaling property for RPC[%s]: %s=%v", opts.Label, key, v)
|
2021-09-27 16:01:40 +00:00
|
|
|
if opts.SkipNulls && v.IsNull() {
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(9).Infof("Skipping null property for RPC[%s]: %s (as requested)", opts.Label, key)
|
2020-03-18 18:39:13 +00:00
|
|
|
} else if opts.SkipInternalKeys && resource.IsInternalPropertyKey(key) {
|
|
|
|
logging.V(9).Infof("Skipping internal property for RPC[%s]: %s (as requested)", opts.Label, key)
|
2017-07-20 16:06:39 +00:00
|
|
|
} else {
|
2021-09-10 20:18:08 +00:00
|
|
|
m, err := MarshalPropertyValue(key, v, opts)
|
2017-09-14 23:40:44 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2017-11-03 20:40:15 +00:00
|
|
|
} else if m != nil {
|
|
|
|
fields[string(key)] = m
|
2017-09-14 23:40:44 +00:00
|
|
|
}
|
2017-02-24 23:41:56 +00:00
|
|
|
}
|
2017-02-20 19:18:47 +00:00
|
|
|
}
|
2017-07-20 16:06:39 +00:00
|
|
|
return &structpb.Struct{
|
|
|
|
Fields: fields,
|
2017-09-14 23:40:44 +00:00
|
|
|
}, nil
|
Initial support for output properties (1 of 3)
This change includes approximately 1/3rd of the change necessary
to support output properties, as per pulumi/lumi#90.
In short, the runtime now has a new hidden type, Latent<T>, which
represents a "speculative" value, whose eventual type will be T,
that we can use during evaluation in various ways. Namely,
operations against Latent<T>s generally produce new Latent<U>s.
During planning, any Latent<T>s that end up in resource properties
are transformed into "unknown" property values. An unknown property
value is legal only during planning-time activities, such as Check,
Name, and InspectChange. As a result, those RPC interfaces have
been updated to include lookaside maps indicating which properties
have unknown values. My intent is to add some helper functions to
make dealing with this circumstance more correct-by-construction.
For now, using an unresolved Latent<T> in a conditional will lead
to an error. See pulumi/lumi#67. Speculating beyond these -- by
supporting iterative planning and application -- is something we
want to support eventually, but it makes sense to do that as an
additive change beyond this initial support. That is a missing 1/3.
Finally, the other missing 1/3rd which will happen much sooner
than the rest is restructuing plan application so that it will
correctly observe resolution of Latent<T> values. Right now, the
evaluation happens in one single pass, prior to the application, and
so Latent<T>s never actually get witnessed in a resolved state.
2017-05-24 00:32:59 +00:00
|
|
|
}
|
|
|
|
|
2017-07-20 16:06:39 +00:00
|
|
|
// MarshalPropertyValue marshals a single resource property value into its "JSON-like" value representation.
|
2021-09-10 20:18:08 +00:00
|
|
|
func MarshalPropertyValue(key resource.PropertyKey, v resource.PropertyValue,
|
2023-03-03 16:36:39 +00:00
|
|
|
opts MarshalOptions,
|
|
|
|
) (*structpb.Value, error) {
|
2017-02-20 19:18:47 +00:00
|
|
|
if v.IsNull() {
|
2017-09-14 23:40:44 +00:00
|
|
|
return MarshalNull(opts), nil
|
2017-02-20 19:18:47 +00:00
|
|
|
} else if v.IsBool() {
|
|
|
|
return &structpb.Value{
|
|
|
|
Kind: &structpb.Value_BoolValue{
|
2017-02-28 19:02:33 +00:00
|
|
|
BoolValue: v.BoolValue(),
|
2017-02-20 19:18:47 +00:00
|
|
|
},
|
2017-09-14 23:40:44 +00:00
|
|
|
}, nil
|
2017-02-20 19:18:47 +00:00
|
|
|
} else if v.IsNumber() {
|
|
|
|
return &structpb.Value{
|
|
|
|
Kind: &structpb.Value_NumberValue{
|
2017-02-28 19:02:33 +00:00
|
|
|
NumberValue: v.NumberValue(),
|
2017-02-20 19:18:47 +00:00
|
|
|
},
|
2017-09-14 23:40:44 +00:00
|
|
|
}, nil
|
2017-02-20 19:18:47 +00:00
|
|
|
} else if v.IsString() {
|
2017-09-14 23:40:44 +00:00
|
|
|
return MarshalString(v.StringValue(), opts), nil
|
2017-02-20 19:18:47 +00:00
|
|
|
} else if v.IsArray() {
|
|
|
|
var elems []*structpb.Value
|
|
|
|
for _, elem := range v.ArrayValue() {
|
2021-09-10 20:18:08 +00:00
|
|
|
e, err := MarshalPropertyValue(key, elem, opts)
|
2017-09-14 23:40:44 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-06-07 20:30:52 +00:00
|
|
|
if e != nil {
|
|
|
|
elems = append(elems, e)
|
|
|
|
}
|
2017-02-20 19:18:47 +00:00
|
|
|
}
|
|
|
|
return &structpb.Value{
|
|
|
|
Kind: &structpb.Value_ListValue{
|
2017-02-28 19:02:33 +00:00
|
|
|
ListValue: &structpb.ListValue{Values: elems},
|
2017-02-20 19:18:47 +00:00
|
|
|
},
|
2017-09-14 23:40:44 +00:00
|
|
|
}, nil
|
2017-07-14 19:28:43 +00:00
|
|
|
} else if v.IsAsset() {
|
2019-08-24 19:27:39 +00:00
|
|
|
if opts.RejectAssets {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("unexpected Asset property value for %q", key)
|
2019-08-24 19:27:39 +00:00
|
|
|
}
|
2017-07-17 17:38:57 +00:00
|
|
|
return MarshalAsset(v.AssetValue(), opts)
|
2017-07-14 19:28:43 +00:00
|
|
|
} else if v.IsArchive() {
|
2019-08-24 19:27:39 +00:00
|
|
|
if opts.RejectAssets {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("unexpected Asset Archive property value for %q", key)
|
2019-08-24 19:27:39 +00:00
|
|
|
}
|
2017-07-17 17:38:57 +00:00
|
|
|
return MarshalArchive(v.ArchiveValue(), opts)
|
2017-02-20 19:18:47 +00:00
|
|
|
} else if v.IsObject() {
|
2017-09-14 23:40:44 +00:00
|
|
|
obj, err := MarshalProperties(v.ObjectValue(), opts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return MarshalStruct(obj, opts), nil
|
2017-05-25 20:19:20 +00:00
|
|
|
} else if v.IsComputed() {
|
2018-01-09 20:21:47 +00:00
|
|
|
if opts.RejectUnknowns {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("unexpected unknown property value for %q", key)
|
2018-01-09 20:21:47 +00:00
|
|
|
} else if opts.KeepUnknowns {
|
2024-02-06 08:22:46 +00:00
|
|
|
if opts.KeepOutputValues && opts.UpgradeToOutputValues {
|
2024-02-02 11:09:58 +00:00
|
|
|
output := resource.NewObjectProperty(resource.PropertyMap{
|
|
|
|
resource.SigKey: resource.NewStringProperty(resource.OutputValueSig),
|
|
|
|
})
|
|
|
|
return MarshalPropertyValue(key, output, opts)
|
|
|
|
}
|
2018-02-05 22:44:23 +00:00
|
|
|
return marshalUnknownProperty(v.Input().Element, opts), nil
|
2017-09-14 23:40:44 +00:00
|
|
|
}
|
2017-11-03 20:40:15 +00:00
|
|
|
return nil, nil // return nil and the caller will ignore it.
|
2017-05-25 20:19:20 +00:00
|
|
|
} else if v.IsOutput() {
|
2021-09-13 16:05:31 +00:00
|
|
|
if !opts.KeepOutputValues {
|
|
|
|
result := v.OutputValue().Element
|
|
|
|
if !v.OutputValue().Known {
|
|
|
|
// Unknown outputs are marshaled the same as Computed.
|
Enable output values by default (#8014)
* Enable output values by default
Enable output values by default in the resource monitor and change the polarity of the envvar from `PULUMI_ENABLE_OUTPUT_VALUES` to `PULUMI_DISABLE_OUTPUT_VALUES`.
* Marshal unknown as unknown string when `!KeepOutputValues`
Marshal all unknown output values as `resource.MakeComputed(resource.NewStringProperty(""))` when not keeping output values, which is consistent with what the SDKs do.
Otherwise, when `v.OutputValue().Element` is nil, `resource.MakeComputed(v.OutputValue().Element)` will be marshaled as a null value rather than as an unknown sentinel.
* Add MarshalOptions.DontSkipOutputs and use where needed
Before we expanded the meaning of `resource.Output`, `MarshalProperties` always skipped output values:
```go
if v.IsOutput() {
logging.V(9).Infof("Skipping output property for RPC[%s]: %v", opts.Label, key)
}
```
As part of expanding the meaning of `resource.Output`, I'd adjusted `MarshalProperties` to only skip output values when the value was unknown and when not keeping output values:
```go
if v.IsOutput() && !v.OutputValue().Known && !opts.KeepOutputValues {
logging.V(9).Infof("Skipping output property for RPC[%s]: %v", opts.Label, key)
}
```
However, this doesn't work the way we want when marshaling properties that include unknown output values to a provider that does not accept outputs. In that case, `opts.KeepOutputValues` will be `false` because we want the marshaler to fall back to returning non-output-values (e.g. unknown sentinel value for unknown output values), but instead of getting the intended fallback values, the unknown output values are skipped (not what we want).
I suspect we may be able to delete the output value skipping in `MarshalProperties` altogether (it's odd that it is skipping `resource.Output` but not `resource.Computed`), but to avoid any unintended side effects of doing that, instead, this commit introduces a new `MarshalOptions.DontSkipOutputs` option that can be set to `true` to opt-in to not skipping output values when marshaling. The check in `MarshalProperties` now looks like this:
```go
if !opts.DontSkipOutputs && v.IsOutput() && !v.OutputValue().Known {
logging.V(9).Infof("Skipping output property for RPC[%s]: %v", opts.Label, key)
}
```
`opts.DontSkipOutputs` is set to `true` when marshaling properties for calls to a provider's `Construct` and `Call`.
* [sdk/nodejs] Deserialize output values
This commit adds support for deserializing output values, which is needed in some cases when serialized inputs are returned as outputs in the SDK.
* [sdk/python] Deserialize output values
This commit adds support for deserializing output values, which is needed in some cases when serialized inputs are returned as outputs in the SDK.
2021-09-24 15:57:04 +00:00
|
|
|
result = resource.MakeComputed(resource.NewStringProperty(""))
|
2021-09-13 16:05:31 +00:00
|
|
|
}
|
|
|
|
if v.OutputValue().Secret {
|
|
|
|
result = resource.MakeSecret(result)
|
|
|
|
}
|
|
|
|
return MarshalPropertyValue(key, result, opts)
|
2017-09-14 23:40:44 +00:00
|
|
|
}
|
2021-09-13 16:05:31 +00:00
|
|
|
obj := resource.PropertyMap{
|
|
|
|
resource.SigKey: resource.NewStringProperty(resource.OutputValueSig),
|
|
|
|
}
|
|
|
|
if v.OutputValue().Known {
|
|
|
|
obj["value"] = v.OutputValue().Element
|
|
|
|
}
|
|
|
|
if v.OutputValue().Secret {
|
|
|
|
obj["secret"] = resource.NewBoolProperty(v.OutputValue().Secret)
|
|
|
|
}
|
|
|
|
if len(v.OutputValue().Dependencies) > 0 {
|
|
|
|
deps := make([]resource.PropertyValue, len(v.OutputValue().Dependencies))
|
|
|
|
for i, dep := range v.OutputValue().Dependencies {
|
|
|
|
deps[i] = resource.NewStringProperty(string(dep))
|
|
|
|
}
|
|
|
|
obj["dependencies"] = resource.NewArrayProperty(deps)
|
|
|
|
}
|
|
|
|
output := resource.NewObjectProperty(obj)
|
|
|
|
return MarshalPropertyValue(key, output, opts)
|
2019-04-12 21:29:08 +00:00
|
|
|
} else if v.IsSecret() {
|
|
|
|
if !opts.KeepSecrets {
|
2019-04-14 04:00:48 +00:00
|
|
|
logging.V(5).Infof("marshalling secret value as raw value as opts.KeepSecrets is false")
|
2021-09-10 20:18:08 +00:00
|
|
|
return MarshalPropertyValue(key, v.SecretValue().Element, opts)
|
2019-04-12 21:29:08 +00:00
|
|
|
}
|
2024-02-06 08:22:46 +00:00
|
|
|
if opts.KeepOutputValues && opts.UpgradeToOutputValues {
|
2024-02-02 11:09:58 +00:00
|
|
|
output := resource.NewObjectProperty(resource.PropertyMap{
|
|
|
|
resource.SigKey: resource.NewStringProperty(resource.OutputValueSig),
|
|
|
|
"secret": resource.NewBoolProperty(true),
|
|
|
|
"value": v.SecretValue().Element,
|
|
|
|
})
|
|
|
|
return MarshalPropertyValue(key, output, opts)
|
|
|
|
}
|
2019-04-12 21:29:08 +00:00
|
|
|
secret := resource.NewObjectProperty(resource.PropertyMap{
|
|
|
|
resource.SigKey: resource.NewStringProperty(resource.SecretSig),
|
|
|
|
"value": v.SecretValue().Element,
|
|
|
|
})
|
2021-09-10 20:18:08 +00:00
|
|
|
return MarshalPropertyValue(key, secret, opts)
|
2020-10-27 17:12:12 +00:00
|
|
|
} else if v.IsResourceReference() {
|
|
|
|
ref := v.ResourceReferenceValue()
|
|
|
|
if !opts.KeepResources {
|
|
|
|
val := string(ref.URN)
|
2021-01-21 23:40:27 +00:00
|
|
|
if !ref.ID.IsNull() {
|
2021-09-10 20:18:08 +00:00
|
|
|
return MarshalPropertyValue(key, ref.ID, opts)
|
2020-10-27 17:12:12 +00:00
|
|
|
}
|
|
|
|
logging.V(5).Infof("marshalling resource value as raw URN or ID as opts.KeepResources is false")
|
|
|
|
return MarshalString(val, opts), nil
|
|
|
|
}
|
|
|
|
m := resource.PropertyMap{
|
|
|
|
resource.SigKey: resource.NewStringProperty(resource.ResourceReferenceSig),
|
|
|
|
"urn": resource.NewStringProperty(string(ref.URN)),
|
|
|
|
}
|
2021-01-21 23:40:27 +00:00
|
|
|
if id, hasID := ref.IDString(); hasID {
|
|
|
|
m["id"] = resource.NewStringProperty(id)
|
2020-10-27 17:12:12 +00:00
|
|
|
}
|
|
|
|
if ref.PackageVersion != "" {
|
|
|
|
m["packageVersion"] = resource.NewStringProperty(ref.PackageVersion)
|
|
|
|
}
|
2021-09-10 20:18:08 +00:00
|
|
|
return MarshalPropertyValue(key, resource.NewObjectProperty(m), opts)
|
2017-02-20 19:18:47 +00:00
|
|
|
}
|
2017-04-08 14:44:02 +00:00
|
|
|
|
2021-09-10 20:18:08 +00:00
|
|
|
contract.Failf("Unrecognized property value in RPC[%s] for %q: %v (type=%v)",
|
|
|
|
opts.Label, key, v.V, reflect.TypeOf(v.V))
|
2017-09-14 23:40:44 +00:00
|
|
|
return nil, nil
|
2017-07-20 16:06:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// marshalUnknownProperty marshals an unknown property in a way that lets us recover its type on the other end.
|
|
|
|
func marshalUnknownProperty(elem resource.PropertyValue, opts MarshalOptions) *structpb.Value {
|
|
|
|
// Normal cases, these get sentinels.
|
|
|
|
if elem.IsBool() {
|
|
|
|
return MarshalString(UnknownBoolValue, opts)
|
|
|
|
} else if elem.IsNumber() {
|
|
|
|
return MarshalString(UnknownNumberValue, opts)
|
|
|
|
} else if elem.IsString() {
|
|
|
|
return MarshalString(UnknownStringValue, opts)
|
|
|
|
} else if elem.IsArray() {
|
|
|
|
return MarshalString(UnknownArrayValue, opts)
|
|
|
|
} else if elem.IsAsset() {
|
|
|
|
return MarshalString(UnknownAssetValue, opts)
|
|
|
|
} else if elem.IsArchive() {
|
|
|
|
return MarshalString(UnknownArchiveValue, opts)
|
|
|
|
} else if elem.IsObject() {
|
|
|
|
return MarshalString(UnknownObjectValue, opts)
|
|
|
|
}
|
|
|
|
|
|
|
|
// If for some reason we end up with a recursive computed/output, just keep digging.
|
|
|
|
if elem.IsComputed() {
|
2018-02-05 22:44:23 +00:00
|
|
|
return marshalUnknownProperty(elem.Input().Element, opts)
|
2017-07-20 16:06:39 +00:00
|
|
|
} else if elem.IsOutput() {
|
|
|
|
return marshalUnknownProperty(elem.OutputValue().Element, opts)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, if a null, we can guess its value! (the one and only...)
|
|
|
|
if elem.IsNull() {
|
|
|
|
return MarshalNull(opts)
|
|
|
|
}
|
|
|
|
|
2017-12-15 15:22:49 +00:00
|
|
|
contract.Failf("Unexpected output/computed property element in RPC[%s]: %v", opts.Label, elem)
|
2017-07-20 16:06:39 +00:00
|
|
|
return nil
|
2017-02-20 19:18:47 +00:00
|
|
|
}
|
|
|
|
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
// UnmarshalProperties unmarshals a "JSON-like" protobuf structure into a new resource property map.
|
2017-09-14 23:40:44 +00:00
|
|
|
func UnmarshalProperties(props *structpb.Struct, opts MarshalOptions) (resource.PropertyMap, error) {
|
Overhaul resources, planning, and environments
This change, part of pulumi/lumi#90, overhauls quite a bit of the
core resource, planning, environments, and related areas.
The biggest amount of movement comes from the splitting of pkg/resource
into multiple sub-packages. This results in:
- pkg/resource: just the core resource data structures.
- pkg/resource/deployment: all planning and deployment logic.
- pkg/resource/environment: all environment, configuration, and
serialized checkpoint structures and logic.
- pkg/resource/plugin: all dynamically loaded analyzer and
provider logic, including the actual loading and RPC mechanisms.
This also splits the resource abstraction up. We now have:
- resource.Resource: a shared interface.
- resource.Object: a resource that is connected to a live object
that will periodically observe mutations due to ongoing
evaluation of computations. Snapshots of its state may be
taken; however, this is purely a "pre-planning" abstraction.
- resource.State: a snapshot of a resource's state that is frozen.
In other words, it is no longer connected to a live object.
This is what will store provider outputs (ID and properties),
and is what may be serialized into a deployment record.
The branch is in a half-baked state as of this change; more changes
are to come...
2017-06-08 23:37:40 +00:00
|
|
|
result := make(resource.PropertyMap)
|
2017-02-20 19:18:47 +00:00
|
|
|
|
|
|
|
// First sort the keys so we enumerate them in order (in case errors happen, we want determinism).
|
|
|
|
var keys []string
|
2017-07-15 01:08:33 +00:00
|
|
|
if props != nil {
|
|
|
|
for k := range props.Fields {
|
|
|
|
keys = append(keys, k)
|
|
|
|
}
|
|
|
|
sort.Strings(keys)
|
2017-02-20 19:18:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// And now unmarshal every field it into the map.
|
2017-07-01 18:51:52 +00:00
|
|
|
for _, key := range keys {
|
|
|
|
pk := resource.PropertyKey(key)
|
2021-09-10 20:18:08 +00:00
|
|
|
v, err := UnmarshalPropertyValue(pk, props.Fields[key], opts)
|
2017-09-14 23:40:44 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2017-11-03 20:40:15 +00:00
|
|
|
} else if v != nil {
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(9).Infof("Unmarshaling property for RPC[%s]: %s=%v", opts.Label, key, v)
|
2017-11-03 20:40:15 +00:00
|
|
|
if opts.SkipNulls && v.IsNull() {
|
2018-05-15 22:28:00 +00:00
|
|
|
logging.V(9).Infof("Skipping unmarshaling for RPC[%s]: %s is null", opts.Label, key)
|
2020-03-18 18:39:13 +00:00
|
|
|
} else if opts.SkipInternalKeys && resource.IsInternalPropertyKey(pk) {
|
|
|
|
logging.V(9).Infof("Skipping unmarshaling for RPC[%s]: %s is internal", opts.Label, key)
|
2017-11-03 20:40:15 +00:00
|
|
|
} else {
|
|
|
|
result[pk] = *v
|
|
|
|
}
|
2017-07-01 18:51:52 +00:00
|
|
|
}
|
2017-02-20 19:18:47 +00:00
|
|
|
}
|
|
|
|
|
2017-09-14 23:40:44 +00:00
|
|
|
return result, nil
|
2017-02-20 19:18:47 +00:00
|
|
|
}
|
|
|
|
|
2017-07-14 19:28:43 +00:00
|
|
|
// UnmarshalPropertyValue unmarshals a single "JSON-like" value into a new property value.
|
2021-09-10 20:18:08 +00:00
|
|
|
func UnmarshalPropertyValue(key resource.PropertyKey, v *structpb.Value,
|
2023-03-03 16:36:39 +00:00
|
|
|
opts MarshalOptions,
|
|
|
|
) (*resource.PropertyValue, error) {
|
2023-02-15 01:06:56 +00:00
|
|
|
contract.Assertf(v != nil, "a value is required")
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
|
|
|
|
switch v.Kind.(type) {
|
|
|
|
case *structpb.Value_NullValue:
|
2017-11-03 20:40:15 +00:00
|
|
|
m := resource.NewNullProperty()
|
|
|
|
return &m, nil
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
case *structpb.Value_BoolValue:
|
2017-11-03 20:40:15 +00:00
|
|
|
m := resource.NewBoolProperty(v.GetBoolValue())
|
|
|
|
return &m, nil
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
case *structpb.Value_NumberValue:
|
2017-11-03 20:40:15 +00:00
|
|
|
m := resource.NewNumberProperty(v.GetNumberValue())
|
|
|
|
return &m, nil
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
case *structpb.Value_StringValue:
|
2017-07-20 16:06:39 +00:00
|
|
|
// If it's a string, it could be an unknown property, or just a regular string.
|
|
|
|
s := v.GetStringValue()
|
|
|
|
if unk, isunk := unmarshalUnknownPropertyValue(s, opts); isunk {
|
2018-01-09 20:21:47 +00:00
|
|
|
if opts.RejectUnknowns {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("unexpected unknown property value for %q", key)
|
2018-01-09 20:21:47 +00:00
|
|
|
} else if opts.KeepUnknowns {
|
2017-11-03 20:40:15 +00:00
|
|
|
return &unk, nil
|
2017-09-14 23:40:44 +00:00
|
|
|
}
|
2017-11-03 20:40:15 +00:00
|
|
|
return nil, nil
|
2017-07-20 16:06:39 +00:00
|
|
|
}
|
2017-11-03 20:40:15 +00:00
|
|
|
m := resource.NewStringProperty(s)
|
|
|
|
return &m, nil
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
case *structpb.Value_ListValue:
|
|
|
|
lst := v.GetListValue()
|
2020-12-23 21:25:48 +00:00
|
|
|
elems := make([]resource.PropertyValue, len(lst.GetValues()))
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
for i, elem := range lst.GetValues() {
|
2021-09-10 20:18:08 +00:00
|
|
|
e, err := UnmarshalPropertyValue(key, elem, opts)
|
2017-09-14 23:40:44 +00:00
|
|
|
if err != nil {
|
2017-11-03 20:40:15 +00:00
|
|
|
return nil, err
|
|
|
|
} else if e != nil {
|
|
|
|
if i == len(elems) {
|
|
|
|
elems = append(elems, *e)
|
|
|
|
} else {
|
|
|
|
elems[i] = *e
|
|
|
|
}
|
2017-09-14 23:40:44 +00:00
|
|
|
}
|
2017-02-20 19:18:47 +00:00
|
|
|
}
|
2017-11-03 20:40:15 +00:00
|
|
|
m := resource.NewArrayProperty(elems)
|
|
|
|
return &m, nil
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
case *structpb.Value_StructValue:
|
2017-07-14 19:28:43 +00:00
|
|
|
// Start by unmarshaling.
|
2017-09-14 23:40:44 +00:00
|
|
|
obj, err := UnmarshalProperties(v.GetStructValue(), opts)
|
|
|
|
if err != nil {
|
2017-11-03 20:40:15 +00:00
|
|
|
return nil, err
|
2017-09-14 23:40:44 +00:00
|
|
|
}
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
|
2017-07-14 19:28:43 +00:00
|
|
|
// Before returning it as an object, check to see if it's a known recoverable type.
|
2017-07-17 17:38:57 +00:00
|
|
|
objmap := obj.Mappable()
|
2019-04-12 21:29:08 +00:00
|
|
|
sig, hasSig := objmap[string(resource.SigKey)]
|
|
|
|
if !hasSig {
|
|
|
|
// This is a weakly-typed object map.
|
|
|
|
m := resource.NewObjectProperty(obj)
|
|
|
|
return &m, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
switch sig {
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
case asset.AssetSig:
|
2019-08-24 19:27:39 +00:00
|
|
|
if opts.RejectAssets {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("unexpected Asset property value for %q", key)
|
2019-08-24 19:27:39 +00:00
|
|
|
}
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
asset, isasset, err := asset.Deserialize(objmap)
|
2019-04-12 21:29:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-08-06 23:32:05 +00:00
|
|
|
// This can only be false with a non-nil error if there is a signature match. We've already verified the
|
|
|
|
// signature.
|
2023-02-15 01:06:56 +00:00
|
|
|
contract.Assertf(isasset, "value must be an asset")
|
2019-04-12 21:29:08 +00:00
|
|
|
if opts.ComputeAssetHashes {
|
2024-05-02 11:32:54 +00:00
|
|
|
if opts.WorkingDirectory == "" {
|
|
|
|
if err = asset.EnsureHash(); err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed to compute asset hash for %q", key)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err = asset.EnsureHashWithWD(opts.WorkingDirectory); err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed to compute asset hash for %q", key)
|
|
|
|
}
|
2017-10-22 20:39:21 +00:00
|
|
|
}
|
2019-04-12 21:29:08 +00:00
|
|
|
}
|
|
|
|
m := resource.NewAssetProperty(asset)
|
|
|
|
return &m, nil
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
case archive.ArchiveSig:
|
2019-08-24 19:27:39 +00:00
|
|
|
if opts.RejectAssets {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("unexpected Asset Archive property value for %q", key)
|
2019-08-24 19:27:39 +00:00
|
|
|
}
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
archive, isarchive, err := archive.Deserialize(objmap)
|
2019-04-12 21:29:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-08-06 23:32:05 +00:00
|
|
|
// This can only be false with a non-nil error if there is a signature match. We've already verified the
|
|
|
|
// signature.
|
2023-02-15 01:06:56 +00:00
|
|
|
contract.Assertf(isarchive, "value must be an archive")
|
2019-04-12 21:29:08 +00:00
|
|
|
if opts.ComputeAssetHashes {
|
2024-05-02 11:32:54 +00:00
|
|
|
if opts.WorkingDirectory == "" {
|
|
|
|
if err = archive.EnsureHash(); err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed to compute archive hash for %q", key)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err = archive.EnsureHashWithWD(opts.WorkingDirectory); err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed to compute archive hash for %q", key)
|
|
|
|
}
|
Implement more precise delete-before-replace semantics. (#2369)
This implements the new algorithm for deciding which resources must be
deleted due to a delete-before-replace operation.
We need to compute the set of resources that may be replaced by a
change to the resource under consideration. We do this by taking the
complete set of transitive dependents on the resource under
consideration and removing any resources that would not be replaced by
changes to their dependencies. We determine whether or not a resource
may be replaced by substituting unknowns for input properties that may
change due to deletion of the resources their value depends on and
calling the resource provider's Diff method.
This is perhaps clearer when described by example. Consider the
following dependency graph:
A
__|__
B C
| _|_
D E F
In this graph, all of B, C, D, E, and F transitively depend on A. It may
be the case, however, that changes to the specific properties of any of
those resources R that would occur if a resource on the path to A were
deleted and recreated may not cause R to be replaced. For example, the
edge from B to A may be a simple dependsOn edge such that a change to
B does not actually influence any of B's input properties. In that case,
neither B nor D would need to be deleted before A could be deleted.
In order to make the above algorithm a reality, the resource monitor
interface has been updated to include a map that associates an input
property key with the list of resources that input property depends on.
Older clients of the resource monitor will leave this map empty, in
which case all input properties will be treated as depending on all
dependencies of the resource. This is probably overly conservative, but
it is less conservative than what we currently implement, and is
certainly correct.
2019-01-28 17:46:30 +00:00
|
|
|
}
|
2017-10-22 20:39:21 +00:00
|
|
|
}
|
2019-04-12 21:29:08 +00:00
|
|
|
m := resource.NewArchiveProperty(archive)
|
|
|
|
return &m, nil
|
|
|
|
case resource.SecretSig:
|
|
|
|
value, ok := obj["value"]
|
|
|
|
if !ok {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("malformed RPC secret: missing value for %q", key)
|
2019-04-12 21:29:08 +00:00
|
|
|
}
|
2021-09-13 16:05:31 +00:00
|
|
|
return unmarshalSecretPropertyValue(value, opts), nil
|
2020-10-27 17:12:12 +00:00
|
|
|
case resource.ResourceReferenceSig:
|
|
|
|
urn, ok := obj["urn"]
|
|
|
|
if !ok {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("malformed resource reference for %q: missing urn", key)
|
2020-10-27 17:12:12 +00:00
|
|
|
}
|
|
|
|
if !urn.IsString() {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("malformed resource reference for %q: urn not a string", key)
|
2020-10-27 17:12:12 +00:00
|
|
|
}
|
|
|
|
|
2020-11-23 19:15:10 +00:00
|
|
|
id, hasID := "", false
|
2020-10-27 17:12:12 +00:00
|
|
|
if idProp, ok := obj["id"]; ok {
|
2020-11-23 19:15:10 +00:00
|
|
|
hasID = true
|
|
|
|
switch {
|
|
|
|
case idProp.IsString():
|
|
|
|
id = idProp.StringValue()
|
|
|
|
case idProp.IsComputed():
|
|
|
|
// Leave the ID empty to indicate that it is unknown.
|
2024-02-06 08:22:46 +00:00
|
|
|
case idProp.IsOutput():
|
|
|
|
if idProp.OutputValue().Known {
|
|
|
|
if !idProp.OutputValue().Element.IsString() {
|
|
|
|
return nil, fmt.Errorf("malformed resource reference for %q: id not a string", key)
|
|
|
|
}
|
|
|
|
id = idProp.OutputValue().Element.StringValue()
|
|
|
|
}
|
2020-11-23 19:15:10 +00:00
|
|
|
default:
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("malformed resource reference for %q: id not a string", key)
|
2020-10-27 17:12:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var packageVersion string
|
|
|
|
if packageVersionProp, ok := obj["packageVersion"]; ok {
|
|
|
|
if !packageVersionProp.IsString() {
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("malformed resource reference for %q: packageVersion not a string", key)
|
2020-10-27 17:12:12 +00:00
|
|
|
}
|
|
|
|
packageVersion = packageVersionProp.StringValue()
|
|
|
|
}
|
|
|
|
|
|
|
|
if !opts.KeepResources {
|
|
|
|
value := urn.StringValue()
|
2021-01-21 23:40:27 +00:00
|
|
|
if hasID {
|
|
|
|
isIDUnknown := id == ""
|
|
|
|
if isIDUnknown && opts.KeepUnknowns {
|
|
|
|
v := structpb.Value{
|
|
|
|
Kind: &structpb.Value_StringValue{StringValue: UnknownStringValue},
|
|
|
|
}
|
2021-09-10 20:18:08 +00:00
|
|
|
return UnmarshalPropertyValue(key, &v, opts)
|
2021-01-21 23:40:27 +00:00
|
|
|
}
|
2020-10-27 17:12:12 +00:00
|
|
|
value = id
|
|
|
|
}
|
|
|
|
r := resource.NewStringProperty(value)
|
|
|
|
return &r, nil
|
|
|
|
}
|
|
|
|
|
2021-01-21 23:40:27 +00:00
|
|
|
var ref resource.PropertyValue
|
|
|
|
if hasID {
|
|
|
|
ref = resource.MakeCustomResourceReference(resource.URN(urn.StringValue()), resource.ID(id), packageVersion)
|
|
|
|
} else {
|
|
|
|
ref = resource.MakeComponentResourceReference(resource.URN(urn.StringValue()), packageVersion)
|
|
|
|
}
|
|
|
|
return &ref, nil
|
2021-09-13 16:05:31 +00:00
|
|
|
case resource.OutputValueSig:
|
|
|
|
value, known := obj["value"]
|
|
|
|
|
|
|
|
var secret bool
|
|
|
|
if secretProp, ok := obj["secret"]; ok {
|
|
|
|
if !secretProp.IsBool() {
|
|
|
|
return nil, fmt.Errorf("malformed output value for %q: secret not a bool", key)
|
|
|
|
}
|
|
|
|
secret = secretProp.BoolValue()
|
|
|
|
}
|
|
|
|
|
|
|
|
if !opts.KeepOutputValues {
|
|
|
|
result := &value
|
|
|
|
if !known {
|
|
|
|
result, err = UnmarshalPropertyValue(key, &structpb.Value{
|
|
|
|
Kind: &structpb.Value_StringValue{StringValue: UnknownStringValue},
|
|
|
|
}, opts)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if secret && result != nil {
|
|
|
|
result = unmarshalSecretPropertyValue(*result, opts)
|
|
|
|
}
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var dependencies []resource.URN
|
|
|
|
if dependenciesProp, ok := obj["dependencies"]; ok {
|
|
|
|
if !dependenciesProp.IsArray() {
|
|
|
|
return nil, fmt.Errorf("malformed output value for %q: dependencies not an array", key)
|
|
|
|
}
|
|
|
|
dependencies = make([]resource.URN, len(dependenciesProp.ArrayValue()))
|
|
|
|
for i, dep := range dependenciesProp.ArrayValue() {
|
|
|
|
if !dep.IsString() {
|
|
|
|
return nil, fmt.Errorf(
|
|
|
|
"malformed output value for %q: element in dependencies not a string", key)
|
|
|
|
}
|
|
|
|
dependencies[i] = resource.URN(dep.StringValue())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
output := resource.NewOutputProperty(resource.Output{
|
|
|
|
Element: value,
|
|
|
|
Known: known,
|
|
|
|
Secret: secret,
|
|
|
|
Dependencies: dependencies,
|
|
|
|
})
|
|
|
|
return &output, nil
|
2019-04-12 21:29:08 +00:00
|
|
|
default:
|
2021-09-10 20:18:08 +00:00
|
|
|
return nil, fmt.Errorf("unrecognized signature '%v' in property map for %q", sig, key)
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
}
|
Implement more precise delete-before-replace semantics. (#2369)
This implements the new algorithm for deciding which resources must be
deleted due to a delete-before-replace operation.
We need to compute the set of resources that may be replaced by a
change to the resource under consideration. We do this by taking the
complete set of transitive dependents on the resource under
consideration and removing any resources that would not be replaced by
changes to their dependencies. We determine whether or not a resource
may be replaced by substituting unknowns for input properties that may
change due to deletion of the resources their value depends on and
calling the resource provider's Diff method.
This is perhaps clearer when described by example. Consider the
following dependency graph:
A
__|__
B C
| _|_
D E F
In this graph, all of B, C, D, E, and F transitively depend on A. It may
be the case, however, that changes to the specific properties of any of
those resources R that would occur if a resource on the path to A were
deleted and recreated may not cause R to be replaced. For example, the
edge from B to A may be a simple dependsOn edge such that a change to
B does not actually influence any of B's input properties. In that case,
neither B nor D would need to be deleted before A could be deleted.
In order to make the above algorithm a reality, the resource monitor
interface has been updated to include a map that associates an input
property key with the list of resources that input property depends on.
Older clients of the resource monitor will leave this map empty, in
which case all input properties will be treated as depending on all
dependencies of the resource. This is probably overly conservative, but
it is less conservative than what we currently implement, and is
certainly correct.
2019-01-28 17:46:30 +00:00
|
|
|
|
Unmap properties on the receive side
This change makes progress on a few things with respect to properly
receiving properties on the engine side, coming from the provider side,
of the RPC boundary. The issues here are twofold:
1. Properties need to get unmapped using a JSON-tag-sensitive
marshaler, so that they are cased properly, etc. For that, we
have a new mapper.Unmap function (which is ultra lame -- see
pulumi/lumi#138).
2. We have the reverse problem with respect to resource IDs: on
the send side, we must translate from URNs (which the engine
knows about) and provider IDs (which the provider knows about);
similarly, then, on the receive side, we must translate from
provider IDs back into URNs.
As a result of these getting fixed, we can now properly marshal the
resulting properties back into the resource object during the plan
execution, alongside propagating and memoizing its ID.
2017-05-31 18:51:46 +00:00
|
|
|
default:
|
2021-09-10 20:18:08 +00:00
|
|
|
contract.Failf("Unrecognized structpb value kind in RPC[%s] for %q: %v", opts.Label, key, reflect.TypeOf(v.Kind))
|
2017-11-03 20:40:15 +00:00
|
|
|
return nil, nil
|
2017-07-14 19:28:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-20 16:06:39 +00:00
|
|
|
func unmarshalUnknownPropertyValue(s string, opts MarshalOptions) (resource.PropertyValue, bool) {
|
|
|
|
var elem resource.PropertyValue
|
|
|
|
var unknown bool
|
|
|
|
switch s {
|
|
|
|
case UnknownBoolValue:
|
|
|
|
elem, unknown = resource.NewBoolProperty(false), true
|
|
|
|
case UnknownNumberValue:
|
|
|
|
elem, unknown = resource.NewNumberProperty(0), true
|
|
|
|
case UnknownStringValue:
|
|
|
|
elem, unknown = resource.NewStringProperty(""), true
|
|
|
|
case UnknownArrayValue:
|
|
|
|
elem, unknown = resource.NewArrayProperty([]resource.PropertyValue{}), true
|
|
|
|
case UnknownAssetValue:
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
elem, unknown = resource.NewAssetProperty(&asset.Asset{}), true
|
2017-07-20 16:06:39 +00:00
|
|
|
case UnknownArchiveValue:
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
elem, unknown = resource.NewArchiveProperty(&archive.Archive{}), true
|
2017-07-20 16:06:39 +00:00
|
|
|
case UnknownObjectValue:
|
|
|
|
elem, unknown = resource.NewObjectProperty(make(resource.PropertyMap)), true
|
|
|
|
}
|
|
|
|
if unknown {
|
2024-02-06 08:22:46 +00:00
|
|
|
if opts.KeepOutputValues && opts.UpgradeToOutputValues {
|
2024-02-02 11:09:58 +00:00
|
|
|
return resource.NewOutputProperty(resource.Output{
|
|
|
|
Element: elem,
|
|
|
|
}), true
|
|
|
|
}
|
2017-07-20 16:06:39 +00:00
|
|
|
comp := resource.Computed{Element: elem}
|
|
|
|
return resource.NewComputedProperty(comp), true
|
|
|
|
}
|
|
|
|
return resource.PropertyValue{}, false
|
|
|
|
}
|
|
|
|
|
2021-09-13 16:05:31 +00:00
|
|
|
func unmarshalSecretPropertyValue(v resource.PropertyValue, opts MarshalOptions) *resource.PropertyValue {
|
|
|
|
if !opts.KeepSecrets {
|
|
|
|
logging.V(5).Infof("unmarshalling secret as raw value, as opts.KeepSecrets is false")
|
|
|
|
return &v
|
|
|
|
}
|
2024-02-02 11:09:58 +00:00
|
|
|
var s resource.PropertyValue
|
2024-02-06 08:22:46 +00:00
|
|
|
if opts.KeepOutputValues && opts.UpgradeToOutputValues {
|
2024-02-02 11:09:58 +00:00
|
|
|
s = resource.NewOutputProperty(resource.Output{
|
|
|
|
Element: v,
|
|
|
|
Secret: true,
|
|
|
|
Known: true,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
s = resource.MakeSecret(v)
|
|
|
|
}
|
2021-09-13 16:05:31 +00:00
|
|
|
return &s
|
|
|
|
}
|
|
|
|
|
2017-07-14 19:28:43 +00:00
|
|
|
// MarshalNull marshals a nil to its protobuf form.
|
|
|
|
func MarshalNull(opts MarshalOptions) *structpb.Value {
|
|
|
|
return &structpb.Value{
|
|
|
|
Kind: &structpb.Value_NullValue{
|
|
|
|
NullValue: structpb.NullValue_NULL_VALUE,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalString marshals a string to its protobuf form.
|
|
|
|
func MarshalString(s string, opts MarshalOptions) *structpb.Value {
|
|
|
|
return &structpb.Value{
|
|
|
|
Kind: &structpb.Value_StringValue{
|
|
|
|
StringValue: s,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalStruct marshals a struct for use in a protobuf field where a value is expected.
|
|
|
|
func MarshalStruct(obj *structpb.Struct, opts MarshalOptions) *structpb.Value {
|
|
|
|
return &structpb.Value{
|
|
|
|
Kind: &structpb.Value_StructValue{
|
|
|
|
StructValue: obj,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalAsset marshals an asset into its wire form for resource provider plugins.
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
func MarshalAsset(v *asset.Asset, opts MarshalOptions) (*structpb.Value, error) {
|
2017-11-21 01:38:09 +00:00
|
|
|
// If we are not providing access to an asset's contents, we simply need to record the fact that this asset existed.
|
|
|
|
// Serialize the asset with only its hash (if present).
|
2017-11-12 19:45:13 +00:00
|
|
|
if opts.ElideAssetContents {
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
v = &asset.Asset{Hash: v.Hash}
|
2017-11-12 19:45:13 +00:00
|
|
|
} else {
|
|
|
|
// Ensure a hash is present if needed.
|
|
|
|
if v.Hash == "" && opts.ComputeAssetHashes {
|
2024-05-02 11:32:54 +00:00
|
|
|
if opts.WorkingDirectory == "" {
|
|
|
|
if err := v.EnsureHash(); err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed to compute asset hash")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err := v.EnsureHashWithWD(opts.WorkingDirectory); err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed to compute asset hash")
|
|
|
|
}
|
2017-11-12 19:45:13 +00:00
|
|
|
}
|
2017-10-22 20:39:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-17 17:38:57 +00:00
|
|
|
// To marshal an asset, we need to first serialize it, and then marshal that.
|
|
|
|
sera := v.Serialize()
|
|
|
|
serap := resource.NewPropertyMapFromMap(sera)
|
2021-09-10 20:18:08 +00:00
|
|
|
pk := resource.PropertyKey(v.URI)
|
|
|
|
return MarshalPropertyValue(pk, resource.NewObjectProperty(serap), opts)
|
2017-07-14 19:28:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalArchive marshals an archive into its wire form for resource provider plugins.
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
func MarshalArchive(v *archive.Archive, opts MarshalOptions) (*structpb.Value, error) {
|
2017-11-21 01:38:09 +00:00
|
|
|
// If we are not providing access to an asset's contents, we simply need to record the fact that this asset existed.
|
|
|
|
// Serialize the asset with only its hash (if present).
|
2017-11-12 19:45:13 +00:00
|
|
|
if opts.ElideAssetContents {
|
Move assets and archives to their own package (#15157)
<!---
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
This PR is motivated by https://github.com/pulumi/pulumi/pull/15145.
`resource.*` should be built on top of `property.Value`,[^1] which means
that `resource`
needs to be able to import `property.Value`, and so `property` cannot
import
`resource`. Since Assets and Archives are both types of properties, they
must be moved out
of `resource`.
[^1]: For example:
https://github.com/pulumi/pulumi/blob/a1d686227cd7e3c70c51bd772450cb0cd57c1479/sdk/go/common/resource/resource_state.go#L35-L36
## Open Question
This PR moves them to their own sub-folders in `resource`. Should
`asset` and `archive`
live somewhere more high level, like `sdk/go/property/{asset,archive}`?
<!--- Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context. -->
## Checklist
- [ ] I have run `make tidy` to update any new dependencies
- [ ] I have run `make lint` to verify my code passes the lint check
- [ ] I have formatted my code using `gofumpt`
<!--- Please provide details if the checkbox below is to be left
unchecked. -->
- [ ] I have added tests that prove my fix is effective or that my
feature works
<!---
User-facing changes require a CHANGELOG entry.
-->
- [ ] 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. -->
2024-01-25 20:39:31 +00:00
|
|
|
v = &archive.Archive{Hash: v.Hash}
|
2017-11-12 19:45:13 +00:00
|
|
|
} else {
|
|
|
|
// Ensure a hash is present if needed.
|
|
|
|
if v.Hash == "" && opts.ComputeAssetHashes {
|
2024-05-02 11:32:54 +00:00
|
|
|
if opts.WorkingDirectory == "" {
|
|
|
|
if err := v.EnsureHash(); err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed to compute archive hash")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if err := v.EnsureHashWithWD(opts.WorkingDirectory); err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "failed to compute archive hash")
|
|
|
|
}
|
2017-11-12 19:45:13 +00:00
|
|
|
}
|
2017-10-22 20:39:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-17 17:38:57 +00:00
|
|
|
// To marshal an archive, we need to first serialize it, and then marshal that.
|
|
|
|
sera := v.Serialize()
|
|
|
|
serap := resource.NewPropertyMapFromMap(sera)
|
2021-09-10 20:18:08 +00:00
|
|
|
pk := resource.PropertyKey(v.URI)
|
|
|
|
return MarshalPropertyValue(pk, resource.NewObjectProperty(serap), opts)
|
2017-02-20 19:18:47 +00:00
|
|
|
}
|