diff --git a/pkg/apitype/core.go b/pkg/apitype/core.go index 8335d6259..e4b2bbdce 100644 --- a/pkg/apitype/core.go +++ b/pkg/apitype/core.go @@ -39,7 +39,7 @@ import ( const ( // DeploymentSchemaVersionCurrent is the current version of the `Deployment` schema. // Any deployments newer than this version will be rejected. - DeploymentSchemaVersionCurrent = 2 + DeploymentSchemaVersionCurrent = 1 ) // VersionedCheckpoint is a version number plus a json document. The version number describes what diff --git a/pkg/apitype/migrate/checkpoint.go b/pkg/apitype/migrate/checkpoint.go index fc9f174f7..a4cd28de5 100644 --- a/pkg/apitype/migrate/checkpoint.go +++ b/pkg/apitype/migrate/checkpoint.go @@ -32,17 +32,3 @@ func UpToCheckpointV2(v1 apitype.CheckpointV1) apitype.CheckpointV2 { v2.Latest = &v2deploy return v2 } - -// DownToCheckpointV1 migrates a CheckpointV2 to a CheckpointV1 -func DownToCheckpointV1(v2 apitype.CheckpointV2) apitype.CheckpointV1 { - var v1 apitype.CheckpointV1 - v1.Stack = v2.Stack - v1.Config = make(config.Map) - for key, value := range v2.Config { - v1.Config[key] = value - } - - v1deploy := DownToDeploymentV1(*v2.Latest) - v1.Latest = &v1deploy - return v1 -} diff --git a/pkg/apitype/migrate/checkpoint_test.go b/pkg/apitype/migrate/checkpoint_test.go index 5942059af..c4a773502 100644 --- a/pkg/apitype/migrate/checkpoint_test.go +++ b/pkg/apitype/migrate/checkpoint_test.go @@ -42,23 +42,3 @@ func TestCheckpointV1ToV2(t *testing.T) { }, v2.Config) assert.Len(t, v2.Latest.Resources, 0) } - -func TestCheckpointV2ToV1(t *testing.T) { - v2 := apitype.CheckpointV2{ - Stack: tokens.QName("mystack"), - Config: config.Map{ - config.MustMakeKey("foo", "number"): config.NewValue("42"), - }, - Latest: &apitype.DeploymentV2{ - Manifest: apitype.ManifestV1{}, - Resources: []apitype.ResourceV2{}, - }, - } - - v1 := DownToCheckpointV1(v2) - assert.Equal(t, tokens.QName("mystack"), v1.Stack) - assert.Equal(t, config.Map{ - config.MustMakeKey("foo", "number"): config.NewValue("42"), - }, v1.Config) - assert.Len(t, v1.Latest.Resources, 0) -} diff --git a/pkg/apitype/migrate/deployment.go b/pkg/apitype/migrate/deployment.go index aaf38501e..da0a3df64 100644 --- a/pkg/apitype/migrate/deployment.go +++ b/pkg/apitype/migrate/deployment.go @@ -27,19 +27,3 @@ func UpToDeploymentV2(v1 apitype.DeploymentV1) apitype.DeploymentV2 { return v2 } - -// DownToDeploymentV1 migrates a deployment from DeploymentV2 to DeploymentV1. -func DownToDeploymentV1(v2 apitype.DeploymentV2) apitype.DeploymentV1 { - var v1 apitype.DeploymentV1 - v1.Manifest = v2.Manifest - for _, res := range v2.Resources { - if res.External { - // External resources were not stored in the deployment prior to V2. - continue - } - - v1.Resources = append(v1.Resources, DownToResourceV1(res)) - } - - return v1 -} diff --git a/pkg/apitype/migrate/deployment_test.go b/pkg/apitype/migrate/deployment_test.go index 3d900d521..831f6ea71 100644 --- a/pkg/apitype/migrate/deployment_test.go +++ b/pkg/apitype/migrate/deployment_test.go @@ -41,24 +41,3 @@ func TestDeploymentV1ToV2(t *testing.T) { assert.Equal(t, resource.URN("a"), v1.Resources[0].URN) assert.Equal(t, resource.URN("b"), v1.Resources[1].URN) } - -func TestDeploymentV2ToV1(t *testing.T) { - v2 := apitype.DeploymentV2{ - Manifest: apitype.ManifestV1{}, - Resources: []apitype.ResourceV2{ - { - URN: resource.URN("a"), - }, - { - URN: resource.URN("b"), - // this resource gets excluded from the V1 snapshot because it's external - External: true, - }, - }, - } - - v1 := DownToDeploymentV1(v2) - assert.Equal(t, v2.Manifest, v1.Manifest) - assert.Len(t, v1.Resources, 1) - assert.Equal(t, resource.URN("a"), v1.Resources[0].URN) -} diff --git a/pkg/apitype/migrate/doc.go b/pkg/apitype/migrate/doc.go index 6a0a9349e..54253202a 100644 --- a/pkg/apitype/migrate/doc.go +++ b/pkg/apitype/migrate/doc.go @@ -13,14 +13,14 @@ // limitations under the License. // Package migrate is responsible for converting to and from the various API -// type versions that are in use in Pulumi. This package can migrate "up" and -// "down" versions for every versioned API that needs to be migrated between -// versions. Today, there are three versionable entities that can be migrated +// type versions that are in use in Pulumi. This package can migrate "up" for +// every versioned API that needs to be migrated between versions. Today, there +// are three versionable entities that can be migrated // with this package: // * Checkpoint, the on-disk format for Fire-and-Forget stack state, // * Deployment, the wire format for service-managed stacks, // * Resource, the wire format for resources saved in deployments, // // The migrations in this package are designed to preserve semantics between -// versions. It is always safe to migrate an entity from one version to another. +// versions. It is always safe to migrate an entity up from one version to another. package migrate diff --git a/pkg/apitype/migrate/resource.go b/pkg/apitype/migrate/resource.go index 41481c445..67d0d0ef0 100644 --- a/pkg/apitype/migrate/resource.go +++ b/pkg/apitype/migrate/resource.go @@ -16,7 +16,6 @@ package migrate import ( "github.com/pulumi/pulumi/pkg/apitype" - "github.com/pulumi/pulumi/pkg/util/contract" ) // UpToResourceV2 migrates a resource from ResourceV1 to ResourceV2. @@ -42,33 +41,12 @@ func UpToResourceV2(v1 apitype.ResourceV1) apitype.ResourceV2 { // lifecycle is not owned by Pulumi. Since all V1 resources have their lifecycles // owned by Pulumi, this is `false` for all V1 resources. v2.External = false - v2.Dependencies = append(v1.Dependencies, v2.Dependencies...) - v2.InitErrors = append(v1.InitErrors, v2.InitErrors...) + // v2.Provider is a reference to a first-class provider associated with this resource. + v2.Provider = "" + // v2.Status is the "dirtiness" of this resource - if the engine knows that the last + // operation against it succeeded or not. + v2.Status = "" + v2.Dependencies = append(v2.Dependencies, v1.Dependencies...) + v2.InitErrors = append(v2.InitErrors, v1.InitErrors...) return v2 } - -// DownToResourceV1 migrates a resource from ResourceV2 to ResourceV1. -func DownToResourceV1(v2 apitype.ResourceV2) apitype.ResourceV1 { - contract.Assertf(!v2.External, "Can't convert a V2 External resource to V1") - var v1 apitype.ResourceV1 - v1.URN = v2.URN - v1.Custom = v2.Custom - v1.Delete = v2.Delete - v1.ID = v2.ID - v1.Type = v2.Type - v1.Inputs = make(map[string]interface{}) - for key, value := range v2.Inputs { - v1.Inputs[key] = value - } - // Defaults was deprecated in v2. - v1.Defaults = make(map[string]interface{}) - v1.Outputs = make(map[string]interface{}) - for key, value := range v2.Outputs { - v1.Outputs[key] = value - } - v1.Parent = v2.Parent - v1.Protect = v2.Protect - v1.Dependencies = append(v1.Dependencies, v2.Dependencies...) - v1.InitErrors = append(v1.InitErrors, v2.InitErrors...) - return v1 -} diff --git a/pkg/apitype/migrate/resource_test.go b/pkg/apitype/migrate/resource_test.go index a271a8997..dc7f9289e 100644 --- a/pkg/apitype/migrate/resource_test.go +++ b/pkg/apitype/migrate/resource_test.go @@ -66,74 +66,6 @@ func TestV1ToV2(t *testing.T) { resource.URN("dep1"), resource.URN("dep2"), }, v2.Dependencies) -} - -func TestV2ToV1(t *testing.T) { - v2 := apitype.ResourceV2{ - URN: resource.URN("foo"), - Custom: true, - Delete: true, - ID: resource.ID("bar"), - Type: tokens.Type("special"), - Inputs: map[string]interface{}{ - "foo_in": "baz", - }, - Outputs: map[string]interface{}{ - "foo_out": "out", - }, - Parent: resource.URN("parent"), - Protect: true, - External: false, - Dependencies: []resource.URN{ - resource.URN("dep1"), - resource.URN("dep2"), - }, - } - - v1 := DownToResourceV1(v2) - assert.Equal(t, resource.URN("foo"), v1.URN) - assert.True(t, v1.Custom) - assert.True(t, v1.Delete) - assert.Equal(t, resource.ID("bar"), v1.ID) - assert.Equal(t, tokens.Type("special"), v1.Type) - assert.Equal(t, map[string]interface{}{ - "foo_in": "baz", - }, v1.Inputs) - assert.Equal(t, map[string]interface{}{}, v1.Defaults) - assert.Equal(t, map[string]interface{}{ - "foo_out": "out", - }, v1.Outputs) - assert.Equal(t, resource.URN("parent"), v1.Parent) - assert.True(t, v1.Protect) - assert.Equal(t, []resource.URN{ - resource.URN("dep1"), - resource.URN("dep2"), - }, v2.Dependencies) -} - -func TestInvalidV2ToV1(t *testing.T) { - v2 := apitype.ResourceV2{ - URN: resource.URN("foo"), - Custom: true, - Delete: true, - ID: resource.ID("bar"), - Type: tokens.Type("special"), - Inputs: map[string]interface{}{ - "foo_in": "baz", - }, - Outputs: map[string]interface{}{ - "foo_out": "out", - }, - Parent: resource.URN("parent"), - Protect: true, - External: true, - Dependencies: []resource.URN{ - resource.URN("dep1"), - resource.URN("dep2"), - }, - } - - assert.Panics(t, func() { - DownToResourceV1(v2) - }) + assert.Empty(t, v2.Provider) + assert.Empty(t, v2.Status) } diff --git a/pkg/backend/cloud/client/client.go b/pkg/backend/cloud/client/client.go index 5c1cb9b04..d5ad11c88 100644 --- a/pkg/backend/cloud/client/client.go +++ b/pkg/backend/cloud/client/client.go @@ -27,7 +27,6 @@ import ( "github.com/pkg/errors" "github.com/pulumi/pulumi/pkg/apitype" - "github.com/pulumi/pulumi/pkg/apitype/migrate" "github.com/pulumi/pulumi/pkg/backend" "github.com/pulumi/pulumi/pkg/diag/colors" "github.com/pulumi/pulumi/pkg/engine" @@ -35,7 +34,6 @@ import ( "github.com/pulumi/pulumi/pkg/resource/config" "github.com/pulumi/pulumi/pkg/tokens" "github.com/pulumi/pulumi/pkg/util/contract" - "github.com/pulumi/pulumi/pkg/util/logging" "github.com/pulumi/pulumi/pkg/workspace" ) @@ -499,13 +497,10 @@ func (pc *Client) InvalidateUpdateCheckpoint(ctx context.Context, update UpdateI } // PatchUpdateCheckpoint patches the checkpoint for the indicated update with the given contents. -func (pc *Client) PatchUpdateCheckpoint(ctx context.Context, update UpdateIdentifier, deployment *apitype.DeploymentV2, +func (pc *Client) PatchUpdateCheckpoint(ctx context.Context, update UpdateIdentifier, deployment *apitype.DeploymentV1, token string) error { - // TODO(pulumi/pulumi#1521): until the service can understand V2 checkpoints, downgrade to V1 before sending it. - logging.V(7).Infof("PatchUpdateCheckpoint: downgrading V2 checkpoint to V1 to speak to service") - v1deployment := migrate.DownToDeploymentV1(*deployment) - rawDeployment, err := json.Marshal(v1deployment) + rawDeployment, err := json.Marshal(deployment) if err != nil { return err } diff --git a/pkg/backend/local/state.go b/pkg/backend/local/state.go index 00b7a2038..5da8436a6 100644 --- a/pkg/backend/local/state.go +++ b/pkg/backend/local/state.go @@ -136,7 +136,7 @@ func (b *localBackend) getStack(name tokens.QName) (config.Map, *deploy.Snapshot } // GetCheckpoint loads a checkpoint file for the given stack in this project, from the current project workspace. -func (b *localBackend) getCheckpoint(stackName tokens.QName) (*apitype.CheckpointV2, error) { +func (b *localBackend) getCheckpoint(stackName tokens.QName) (*apitype.CheckpointV1, error) { chkpath := b.stackPath(stackName) bytes, err := ioutil.ReadFile(chkpath) if err != nil { diff --git a/pkg/operations/resources_test.go b/pkg/operations/resources_test.go index dae902315..95a1dfbd3 100644 --- a/pkg/operations/resources_test.go +++ b/pkg/operations/resources_test.go @@ -27,7 +27,7 @@ import ( ) func getPulumiResources(t *testing.T, path string) *Resource { - var checkpoint apitype.CheckpointV2 + var checkpoint apitype.CheckpointV1 byts, err := ioutil.ReadFile(path) assert.NoError(t, err) err = json.Unmarshal(byts, &checkpoint) diff --git a/pkg/resource/stack/checkpoint.go b/pkg/resource/stack/checkpoint.go index 3958926df..41bef0edd 100644 --- a/pkg/resource/stack/checkpoint.go +++ b/pkg/resource/stack/checkpoint.go @@ -23,7 +23,6 @@ import ( "github.com/pkg/errors" "github.com/pulumi/pulumi/pkg/apitype" - "github.com/pulumi/pulumi/pkg/apitype/migrate" "github.com/pulumi/pulumi/pkg/resource" "github.com/pulumi/pulumi/pkg/resource/config" "github.com/pulumi/pulumi/pkg/resource/deploy" @@ -32,7 +31,7 @@ import ( "github.com/pulumi/pulumi/pkg/workspace" ) -func UnmarshalVersionedCheckpointToLatestCheckpoint(bytes []byte) (*apitype.CheckpointV2, error) { +func UnmarshalVersionedCheckpointToLatestCheckpoint(bytes []byte) (*apitype.CheckpointV1, error) { var versionedCheckpoint apitype.VersionedCheckpoint if err := json.Unmarshal(bytes, &versionedCheckpoint); err != nil { return nil, err @@ -49,22 +48,13 @@ func UnmarshalVersionedCheckpointToLatestCheckpoint(bytes []byte) (*apitype.Chec return nil, err } - v2checkpoint := migrate.UpToCheckpointV2(checkpoint) - return &v2checkpoint, nil + return &checkpoint, nil case 1: var checkpoint apitype.CheckpointV1 if err := json.Unmarshal(versionedCheckpoint.Checkpoint, &checkpoint); err != nil { return nil, err } - v2checkpoint := migrate.UpToCheckpointV2(checkpoint) - return &v2checkpoint, nil - case 2: - var checkpoint apitype.CheckpointV2 - if err := json.Unmarshal(versionedCheckpoint.Checkpoint, &checkpoint); err != nil { - return nil, err - } - return &checkpoint, nil default: return nil, errors.Errorf("unsupported checkpoint version %d", versionedCheckpoint.Version) @@ -74,12 +64,12 @@ func UnmarshalVersionedCheckpointToLatestCheckpoint(bytes []byte) (*apitype.Chec // SerializeCheckpoint turns a snapshot into a data structure suitable for serialization. func SerializeCheckpoint(stack tokens.QName, config config.Map, snap *deploy.Snapshot) *apitype.VersionedCheckpoint { // If snap is nil, that's okay, we will just create an empty deployment; otherwise, serialize the whole snapshot. - var latest *apitype.DeploymentV2 + var latest *apitype.DeploymentV1 if snap != nil { latest = SerializeDeployment(snap) } - b, err := json.Marshal(apitype.CheckpointV2{ + b, err := json.Marshal(apitype.CheckpointV1{ Stack: stack, Config: config, Latest: latest, @@ -93,7 +83,7 @@ func SerializeCheckpoint(stack tokens.QName, config config.Map, snap *deploy.Sna } // DeserializeCheckpoint takes a serialized deployment record and returns its associated snapshot. -func DeserializeCheckpoint(chkpoint *apitype.CheckpointV2) (*deploy.Snapshot, error) { +func DeserializeCheckpoint(chkpoint *apitype.CheckpointV1) (*deploy.Snapshot, error) { contract.Require(chkpoint != nil, "chkpoint") var snap *deploy.Snapshot diff --git a/pkg/resource/stack/deployment.go b/pkg/resource/stack/deployment.go index abed994c2..4aad04c24 100644 --- a/pkg/resource/stack/deployment.go +++ b/pkg/resource/stack/deployment.go @@ -20,11 +20,9 @@ import ( "reflect" "github.com/pulumi/pulumi/pkg/apitype" - "github.com/pulumi/pulumi/pkg/apitype/migrate" "github.com/pulumi/pulumi/pkg/resource" "github.com/pulumi/pulumi/pkg/resource/deploy" "github.com/pulumi/pulumi/pkg/util/contract" - "github.com/pulumi/pulumi/pkg/util/logging" ) const ( @@ -46,7 +44,7 @@ var ( ) // SerializeDeployment serializes an entire snapshot as a deploy record. -func SerializeDeployment(snap *deploy.Snapshot) *apitype.DeploymentV2 { +func SerializeDeployment(snap *deploy.Snapshot) *apitype.DeploymentV1 { contract.Require(snap != nil, "snap") // Capture the version information into a manifest. @@ -69,12 +67,12 @@ func SerializeDeployment(snap *deploy.Snapshot) *apitype.DeploymentV2 { } // Serialize all vertices and only include a vertex section if non-empty. - var resources []apitype.ResourceV2 + var resources []apitype.ResourceV1 for _, res := range snap.Resources { resources = append(resources, SerializeResource(res)) } - return &apitype.DeploymentV2{ + return &apitype.DeploymentV1{ Manifest: manifest, Resources: resources, } @@ -92,30 +90,19 @@ func DeserializeDeployment(deployment *apitype.UntypedDeployment) (*deploy.Snaps return nil, ErrDeploymentSchemaVersionTooOld } - var checkpoint apitype.CheckpointV2 + var checkpoint apitype.CheckpointV1 switch deployment.Version { case 1: - v1checkpoint := apitype.CheckpointV1{} - if err := json.Unmarshal([]byte(deployment.Deployment), &v1checkpoint.Latest); err != nil { + if err := json.Unmarshal([]byte(deployment.Deployment), &checkpoint.Latest); err != nil { return nil, err } - - logging.V(7).Infof("DeserializeDeployment: migrating V1 checkpoint to V2") - checkpoint = migrate.UpToCheckpointV2(v1checkpoint) - case 2: - v2checkpoint := apitype.CheckpointV2{} - if err := json.Unmarshal([]byte(deployment.Deployment), &v2checkpoint.Latest); err != nil { - return nil, err - } - - checkpoint = v2checkpoint } return DeserializeCheckpoint(&checkpoint) } // SerializeResource turns a resource into a structure suitable for serialization. -func SerializeResource(res *resource.State) apitype.ResourceV2 { +func SerializeResource(res *resource.State) apitype.ResourceV1 { contract.Assert(res != nil) contract.Assertf(string(res.URN) != "", "Unexpected empty resource resource.URN") @@ -129,7 +116,7 @@ func SerializeResource(res *resource.State) apitype.ResourceV2 { outputs = SerializeProperties(outp) } - return apitype.ResourceV2{ + return apitype.ResourceV1{ URN: res.URN, Custom: res.Custom, Delete: res.Delete, @@ -190,7 +177,7 @@ func SerializePropertyValue(prop resource.PropertyValue) interface{} { } // DeserializeResource turns a serialized resource back into its usual form. -func DeserializeResource(res apitype.ResourceV2) (*resource.State, error) { +func DeserializeResource(res apitype.ResourceV1) (*resource.State, error) { // Deserialize the resource properties, if they exist. inputs, err := DeserializeProperties(res.Inputs) if err != nil {