2017-06-26 23:46:34 +02:00
// Copyright 2016-2017, Pulumi Corporation. All rights reserved.
2017-02-22 03:31:43 +01:00
2017-10-16 21:04:35 +02:00
package stack
2017-02-22 03:31:43 +01:00
import (
2017-02-22 23:32:03 +01:00
"reflect"
2017-02-26 20:20:14 +01:00
"time"
2017-02-22 23:32:03 +01:00
2017-09-22 04:18:21 +02:00
"github.com/pulumi/pulumi/pkg/resource"
"github.com/pulumi/pulumi/pkg/resource/deploy"
"github.com/pulumi/pulumi/pkg/tokens"
"github.com/pulumi/pulumi/pkg/util/contract"
2018-02-06 18:57:32 +01:00
"github.com/pulumi/pulumi/pkg/workspace"
2017-02-22 03:31:43 +01:00
)
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 20:50:47 +02:00
// Deployment is a serializable, flattened LumiGL graph structure, representing a deploy. It is similar
2017-06-10 03:34:37 +02:00
// to the actual Snapshot structure, except that it flattens and rearranges a few data structures for serializability.
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 20:50:47 +02:00
// Over time, we also expect this to gather more information about deploys themselves.
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-09 01:37:40 +02:00
type Deployment struct {
2017-12-01 22:50:32 +01:00
Manifest Manifest ` json:"manifest" yaml:"manifest" ` // the deployment's manifest.
2017-10-19 00:37:18 +02:00
Resources [ ] Resource ` json:"resources,omitempty" yaml:"resources,omitempty" ` // an array of resources.
2017-02-22 03:31:43 +01:00
}
2017-12-01 22:50:32 +01:00
// Manifest captures meta-information about this checkpoint file, such as versions of binaries, etc.
type Manifest struct {
Time time . Time ` json:"time" yaml:"time" ` // the time of the deploy.
Magic string ` json:"magic" yaml:"magic" ` // a magic cookie.
Version string ` json:"version" yaml:"version" ` // the version of the Pulumi CLI.
Plugins [ ] PluginInfo ` json:"plugins,omitempty" yaml:"plugins,omitempty" ` // the plugin binary versions.
}
// PluginInfo captures the version and information about a plugin.
type PluginInfo struct {
2018-02-06 18:57:32 +01:00
Name string ` json:"name" yaml:"name" `
2018-02-21 19:32:31 +01:00
Path string ` json:"path" yaml:"path" `
2018-02-06 18:57:32 +01:00
Type workspace . PluginKind ` json:"type" yaml:"type" `
Version string ` json:"version" yaml:"version" `
2017-12-01 22:50:32 +01:00
}
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 20:50:47 +02:00
// Resource is a serializable vertex within a LumiGL graph, specifically for resource snapshots.
2017-11-20 19:08:59 +01:00
// nolint: lll
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 20:50:47 +02:00
type Resource struct {
2018-02-22 00:11:21 +01:00
URN resource . URN ` json:"urn" yaml:"urn" ` // the URN for this resource.
Custom bool ` json:"custom" yaml:"custom" ` // if this is a custom resource managed by a plugin.
Delete bool ` json:"delete,omitempty" yaml:"delete,omitempty" ` // if this should be deleted during the next update.
ID resource . ID ` json:"id,omitempty" yaml:"id,omitempty" ` // the provider ID for this resource, if any.
Type tokens . Type ` json:"type" yaml:"type" ` // this resource's full type token.
Inputs map [ string ] interface { } ` json:"inputs,omitempty" yaml:"inputs,omitempty" ` // the input properties from the provider (or the program for ressources with defaults).
Defaults map [ string ] interface { } ` json:"defaults,omitempty" yaml:"defaults,omitempty" ` // the default property values from the provider (DEPRECATED, see #637).
Outputs map [ string ] interface { } ` json:"outputs,omitempty" yaml:"outputs,omitempty" ` // the output properties from the resource provider.
Parent resource . URN ` json:"parent,omitempty" yaml:"parent,omitempty" ` // an optional parent URN if this is a child resource.
Protect bool ` json:"protect,omitempty" yaml:"protect,omitempty" ` // true if this resource is protected, and cannot be deleted.
Dependencies [ ] resource . URN ` json:"dependencies" yaml:"dependencies" ` // the dependency edges for this resource
2017-02-22 03:31:43 +01:00
}
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 20:50:47 +02:00
// SerializeDeployment serializes an entire snapshot as a deploy record.
func SerializeDeployment ( snap * deploy . Snapshot ) * Deployment {
2017-12-01 22:50:32 +01:00
// Capture the version information into a manifest.
manifest := Manifest {
Time : snap . Manifest . Time ,
Magic : snap . Manifest . Magic ,
Version : snap . Manifest . Version ,
}
for _ , plug := range snap . Manifest . Plugins {
2018-02-06 18:57:32 +01:00
var version string
if plug . Version != nil {
version = plug . Version . String ( )
}
2017-12-01 22:50:32 +01:00
manifest . Plugins = append ( manifest . Plugins , PluginInfo {
Name : plug . Name ,
2018-02-21 19:32:31 +01:00
Path : plug . Path ,
2018-02-06 18:57:32 +01:00
Type : plug . Kind ,
Version : version ,
2017-12-01 22:50:32 +01:00
} )
}
2017-02-22 03:31:43 +01:00
// Serialize all vertices and only include a vertex section if non-empty.
2017-10-05 23:08:35 +02:00
var resources [ ] Resource
for _ , res := range snap . Resources {
resources = append ( resources , SerializeResource ( res ) )
2017-02-22 03:31:43 +01: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-09 01:37:40 +02:00
return & Deployment {
2017-12-01 22:50:32 +01:00
Manifest : manifest ,
2017-10-05 23:08:35 +02:00
Resources : resources ,
2017-02-22 03:31:43 +01:00
}
}
2017-10-05 23:08:35 +02:00
// SerializeResource turns a resource into a structure suitable for serialization.
func SerializeResource ( res * resource . State ) Resource {
2017-02-22 03:31:43 +01:00
contract . Assert ( res != nil )
2017-10-05 23:08:35 +02:00
contract . Assertf ( string ( res . URN ) != "" , "Unexpected empty resource resource.URN" )
2017-02-22 03:31:43 +01:00
2017-06-05 04:24:48 +02:00
// Serialize all input and output properties recursively, and add them if non-empty.
2017-06-07 01:42:14 +02:00
var inputs map [ string ] interface { }
2017-08-01 03:26:15 +02:00
if inp := res . Inputs ; inp != nil {
2017-06-10 03:34:37 +02:00
inputs = SerializeProperties ( inp )
2017-06-07 01:42:14 +02:00
}
var outputs map [ string ] interface { }
2017-08-01 03:26:15 +02:00
if outp := res . Outputs ; outp != nil {
2017-06-10 03:34:37 +02:00
outputs = SerializeProperties ( outp )
2017-06-07 01:42:14 +02:00
}
2017-02-22 03:31:43 +01:00
2017-10-05 23:08:35 +02:00
return Resource {
2018-02-22 00:11:21 +01:00
URN : res . URN ,
Custom : res . Custom ,
Delete : res . Delete ,
ID : res . ID ,
Type : res . Type ,
Parent : res . Parent ,
Inputs : inputs ,
Outputs : outputs ,
Protect : res . Protect ,
Dependencies : res . Dependencies ,
2017-02-22 03:31:43 +01:00
}
}
2017-06-10 03:34:37 +02:00
// SerializeProperties serializes a resource property bag so that it's suitable for serialization.
func SerializeProperties ( props resource . PropertyMap ) map [ string ] interface { } {
2017-06-07 01:42:14 +02:00
dst := make ( map [ string ] interface { } )
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 20:50:47 +02:00
for _ , k := range props . StableKeys ( ) {
2017-06-10 03:34:37 +02:00
if v := SerializePropertyValue ( props [ k ] ) ; v != nil {
2017-06-05 04:24:48 +02:00
dst [ string ( k ) ] = v
2017-02-22 23:32:03 +01:00
}
}
2017-06-05 04:24:48 +02:00
return dst
2017-02-22 23:32:03 +01:00
}
2017-06-10 03:34:37 +02:00
// SerializePropertyValue serializes a resource property value so that it's suitable for serialization.
func SerializePropertyValue ( prop resource . PropertyValue ) interface { } {
2017-06-05 04:24:48 +02:00
// Skip nulls and "outputs"; the former needn't be serialized, and the latter happens if there is an output
// that hasn't materialized (either because we're serializing inputs or the provider didn't give us the value).
2017-10-24 01:02:28 +02:00
if prop . IsComputed ( ) || ! prop . HasValue ( ) {
2017-06-01 17:23:59 +02:00
return nil
2017-02-22 03:31:43 +01:00
}
// For arrays, make sure to recurse.
if prop . IsArray ( ) {
2017-06-07 01:42:14 +02:00
srcarr := prop . ArrayValue ( )
dstarr := make ( [ ] interface { } , len ( srcarr ) )
for i , elem := range prop . ArrayValue ( ) {
2017-06-10 03:34:37 +02:00
dstarr [ i ] = SerializePropertyValue ( elem )
2017-02-22 03:31:43 +01:00
}
2017-06-07 01:42:14 +02:00
return dstarr
2017-02-22 03:31:43 +01:00
}
// Also for objects, recurse and use naked properties.
if prop . IsObject ( ) {
2017-06-10 03:34:37 +02:00
return SerializeProperties ( prop . ObjectValue ( ) )
2017-02-22 03:31:43 +01:00
}
2017-07-17 19:38:57 +02:00
// For assets, we need to serialize them a little carefully, so we can recover them afterwards.
if prop . IsAsset ( ) {
return prop . AssetValue ( ) . Serialize ( )
} else if prop . IsArchive ( ) {
return prop . ArchiveValue ( ) . Serialize ( )
}
2017-02-22 03:31:43 +01:00
// All others are returned as-is.
2017-06-01 17:23:59 +02:00
return prop . V
2017-02-22 03:31:43 +01:00
}
2017-10-05 23:08:35 +02:00
// DeserializeResource turns a serialized resource back into its usual form.
2017-10-22 22:39:21 +02:00
func DeserializeResource ( res Resource ) ( * resource . State , error ) {
2017-10-05 23:08:35 +02:00
// Deserialize the resource properties, if they exist.
2017-10-22 22:39:21 +02:00
inputs , err := DeserializeProperties ( res . Inputs )
if err != nil {
return nil , err
}
defaults , err := DeserializeProperties ( res . Defaults )
if err != nil {
return nil , err
}
outputs , err := DeserializeProperties ( res . Outputs )
if err != nil {
return nil , err
}
2017-10-05 23:08:35 +02:00
2017-12-03 01:34:16 +01:00
// If this is an old checkpoint that still had defaults, merge the inputs into the defaults.
//
// NOTE: we will remove support for defaults entirely in the future. See #637.
if inputs != nil && defaults != nil {
inputs = defaults . Merge ( inputs )
}
2017-10-22 22:39:21 +02:00
return resource . NewState (
2018-02-22 00:11:21 +01:00
res . Type , res . URN , res . Custom , res . Delete , res . ID , inputs , outputs , res . Parent , res . Protect , res . Dependencies ) , nil
2017-10-05 23:08:35 +02:00
}
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 20:50:47 +02:00
// DeserializeProperties deserializes an entire map of deploy properties into a resource property map.
2017-10-22 22:39:21 +02:00
func DeserializeProperties ( props map [ string ] interface { } ) ( resource . PropertyMap , error ) {
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 20:50:47 +02:00
result := make ( resource . PropertyMap )
2017-02-22 23:32:03 +01:00
for k , prop := range props {
2017-10-22 22:39:21 +02:00
desprop , err := DeserializePropertyValue ( prop )
if err != nil {
return nil , err
}
result [ resource . PropertyKey ( k ) ] = desprop
2017-02-22 23:32:03 +01:00
}
2017-10-22 22:39:21 +02:00
return result , nil
2017-02-22 23:32:03 +01:00
}
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 20:50:47 +02:00
// DeserializePropertyValue deserializes a single deploy property into a resource property value.
2017-10-22 22:39:21 +02:00
func DeserializePropertyValue ( v interface { } ) ( resource . PropertyValue , error ) {
2017-02-22 23:32:03 +01:00
if v != nil {
switch w := v . ( type ) {
case bool :
2017-10-22 22:39:21 +02:00
return resource . NewBoolProperty ( w ) , nil
2017-02-22 23:32:03 +01:00
case float64 :
2017-10-22 22:39:21 +02:00
return resource . NewNumberProperty ( w ) , nil
2017-02-22 23:32:03 +01:00
case string :
2017-10-22 22:39:21 +02:00
return resource . NewStringProperty ( w ) , nil
2017-02-22 23:32:03 +01:00
case [ ] interface { } :
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 20:50:47 +02:00
var arr [ ] resource . PropertyValue
2017-02-22 23:32:03 +01:00
for _ , elem := range w {
2017-10-22 22:39:21 +02:00
ev , err := DeserializePropertyValue ( elem )
if err != nil {
return resource . PropertyValue { } , err
}
arr = append ( arr , ev )
2017-02-22 23:32:03 +01:00
}
2017-10-22 22:39:21 +02:00
return resource . NewArrayProperty ( arr ) , nil
2017-02-22 23:32:03 +01:00
case map [ string ] interface { } :
2017-10-22 22:39:21 +02:00
obj , err := DeserializeProperties ( w )
if err != nil {
return resource . PropertyValue { } , err
}
2017-07-17 19:38:57 +02:00
// This could be an asset or archive; if so, recover its type.
objmap := obj . Mappable ( )
2017-10-23 00:54:44 +02:00
asset , isasset , err := resource . DeserializeAsset ( objmap )
2017-10-22 22:39:21 +02:00
if err != nil {
return resource . PropertyValue { } , err
} else if isasset {
return resource . NewAssetProperty ( asset ) , nil
}
2017-10-23 00:54:44 +02:00
archive , isarchive , err := resource . DeserializeArchive ( objmap )
2017-10-22 22:39:21 +02:00
if err != nil {
return resource . PropertyValue { } , err
} else if isarchive {
return resource . NewArchiveProperty ( archive ) , nil
2017-07-17 19:38:57 +02:00
}
// Otherwise, it's just a weakly typed object map.
2017-10-22 22:39:21 +02:00
return resource . NewObjectProperty ( obj ) , nil
2017-02-22 23:32:03 +01:00
default :
contract . Failf ( "Unrecognized property type: %v" , reflect . ValueOf ( v ) )
}
}
2017-10-22 22:39:21 +02:00
return resource . NewNullProperty ( ) , nil
2017-02-22 03:31:43 +01:00
}