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"
|
Implement components
This change implements core support for "components" in the Pulumi
Fabric. This work is described further in pulumi/pulumi#340, where
we are still discussing some of the finer points.
In a nutshell, resources no longer imply external providers. It's
entirely possible to have a resource that logically represents
something but without having a physical manifestation that needs to
be tracked and managed by our typical CRUD operations.
For example, the aws/serverless/Function helper is one such type.
It aggregates Lambda-related resources and exposes a nice interface.
All of the Pulumi Cloud Framework resources are also examples.
To indicate that a resource does participate in the usual CRUD resource
provider, it simply derives from ExternalResource instead of Resource.
All resources now have the ability to adopt children. This is purely
a metadata/tagging thing, and will help us roll up displays, provide
attribution to the developer, and even hide aspects of the resource
graph as appropriate (e.g., when they are implementation details).
Our use of this capability is ultra limited right now; in fact, the
only place we display children is in the CLI output. For instance:
+ aws:serverless:Function: (create)
[urn=urn:pulumi:demo::serverless::aws:serverless:Function::mylambda]
=> urn:pulumi:demo::serverless::aws:iam/role:Role::mylambda-iamrole
=> urn:pulumi:demo::serverless::aws:iam/rolePolicyAttachment:RolePolicyAttachment::mylambda-iampolicy-0
=> urn:pulumi:demo::serverless::aws:lambda/function:Function::mylambda
The bit indicating whether a resource is external or not is tracked
in the resulting checkpoint file, along with any of its children.
2017-10-14 23:18:43 +02:00
|
|
|
"sort"
|
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"
|
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-10-20 22:21:04 +02:00
|
|
|
Time time.Time `json:"time" yaml:"time"` // the time of the deploy.
|
|
|
|
Info interface{} `json:"info,omitempty" yaml:"info,omitempty"` // optional information about the source.
|
|
|
|
Resources []Resource `json:"resources,omitempty" yaml:"resources,omitempty"` // an array of resources.
|
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
|
|
|
// Resource is a serializable vertex within a LumiGL graph, specifically for resource snapshots.
|
|
|
|
type Resource struct {
|
2017-10-20 22:21:04 +02: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 program.
|
|
|
|
Defaults map[string]interface{} `json:"defaults,omitempty" yaml:"defaults,omitempty"` // the default property values from the provider.
|
|
|
|
Outputs map[string]interface{} `json:"outputs,omitempty" yaml:"outputs,omitempty"` // the output properties from the resource provider.
|
|
|
|
Children []string `json:"children,omitempty" yaml:"children,omitempty"` // an optional list of child resources.
|
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-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-10-10 03:02:27 +02:00
|
|
|
Time: snap.Time,
|
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
|
|
|
Info: snap.Info,
|
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
|
|
|
}
|
2017-08-01 03:26:15 +02:00
|
|
|
var defaults map[string]interface{}
|
|
|
|
if defp := res.Defaults; defp != nil {
|
|
|
|
defaults = SerializeProperties(defp)
|
|
|
|
}
|
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
|
|
|
|
Implement components
This change implements core support for "components" in the Pulumi
Fabric. This work is described further in pulumi/pulumi#340, where
we are still discussing some of the finer points.
In a nutshell, resources no longer imply external providers. It's
entirely possible to have a resource that logically represents
something but without having a physical manifestation that needs to
be tracked and managed by our typical CRUD operations.
For example, the aws/serverless/Function helper is one such type.
It aggregates Lambda-related resources and exposes a nice interface.
All of the Pulumi Cloud Framework resources are also examples.
To indicate that a resource does participate in the usual CRUD resource
provider, it simply derives from ExternalResource instead of Resource.
All resources now have the ability to adopt children. This is purely
a metadata/tagging thing, and will help us roll up displays, provide
attribution to the developer, and even hide aspects of the resource
graph as appropriate (e.g., when they are implementation details).
Our use of this capability is ultra limited right now; in fact, the
only place we display children is in the CLI output. For instance:
+ aws:serverless:Function: (create)
[urn=urn:pulumi:demo::serverless::aws:serverless:Function::mylambda]
=> urn:pulumi:demo::serverless::aws:iam/role:Role::mylambda-iamrole
=> urn:pulumi:demo::serverless::aws:iam/rolePolicyAttachment:RolePolicyAttachment::mylambda-iampolicy-0
=> urn:pulumi:demo::serverless::aws:lambda/function:Function::mylambda
The bit indicating whether a resource is external or not is tracked
in the resulting checkpoint file, along with any of its children.
2017-10-14 23:18:43 +02:00
|
|
|
// Sort the list of children.
|
|
|
|
var children []string
|
|
|
|
for _, child := range res.Children {
|
|
|
|
children = append(children, string(child))
|
|
|
|
}
|
|
|
|
sort.Strings(children)
|
|
|
|
|
2017-10-05 23:08:35 +02:00
|
|
|
return Resource{
|
|
|
|
URN: res.URN,
|
2017-10-15 12:52:04 +02:00
|
|
|
Custom: res.Custom,
|
2017-10-05 23:08:35 +02:00
|
|
|
Delete: res.Delete,
|
2017-08-01 03:26:15 +02:00
|
|
|
ID: res.ID,
|
2017-08-30 03:24:12 +02:00
|
|
|
Type: res.Type,
|
Implement components
This change implements core support for "components" in the Pulumi
Fabric. This work is described further in pulumi/pulumi#340, where
we are still discussing some of the finer points.
In a nutshell, resources no longer imply external providers. It's
entirely possible to have a resource that logically represents
something but without having a physical manifestation that needs to
be tracked and managed by our typical CRUD operations.
For example, the aws/serverless/Function helper is one such type.
It aggregates Lambda-related resources and exposes a nice interface.
All of the Pulumi Cloud Framework resources are also examples.
To indicate that a resource does participate in the usual CRUD resource
provider, it simply derives from ExternalResource instead of Resource.
All resources now have the ability to adopt children. This is purely
a metadata/tagging thing, and will help us roll up displays, provide
attribution to the developer, and even hide aspects of the resource
graph as appropriate (e.g., when they are implementation details).
Our use of this capability is ultra limited right now; in fact, the
only place we display children is in the CLI output. For instance:
+ aws:serverless:Function: (create)
[urn=urn:pulumi:demo::serverless::aws:serverless:Function::mylambda]
=> urn:pulumi:demo::serverless::aws:iam/role:Role::mylambda-iamrole
=> urn:pulumi:demo::serverless::aws:iam/rolePolicyAttachment:RolePolicyAttachment::mylambda-iampolicy-0
=> urn:pulumi:demo::serverless::aws:lambda/function:Function::mylambda
The bit indicating whether a resource is external or not is tracked
in the resulting checkpoint file, along with any of its children.
2017-10-14 23:18:43 +02:00
|
|
|
Children: children,
|
2017-08-01 03:26:15 +02:00
|
|
|
Inputs: inputs,
|
|
|
|
Defaults: defaults,
|
|
|
|
Outputs: outputs,
|
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
|
|
|
|
|
|
|
var children []resource.URN
|
|
|
|
for _, child := range res.Children {
|
|
|
|
children = append(children, resource.URN(child))
|
|
|
|
}
|
|
|
|
|
2017-10-22 22:39:21 +02:00
|
|
|
return resource.NewState(
|
|
|
|
res.Type, res.URN, res.Custom, res.Delete, res.ID, inputs, defaults, outputs, children), 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
|
|
|
}
|