pulumi/pkg/backend/diy/meta_test.go

232 lines
5.7 KiB
Go

// Copyright 2016-2023, Pulumi Corporation.
//
// 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.
package diy
import (
"context"
"path/filepath"
"testing"
"github.com/pulumi/pulumi/sdk/v3/go/common/env"
"github.com/pulumi/pulumi/sdk/v3/go/common/testing/diagtest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gocloud.dev/blob/fileblob"
"gocloud.dev/blob/memblob"
)
func TestEnsurePulumiMeta(t *testing.T) {
t.Parallel()
mkmap := func(value string) env.MapStore {
m := make(env.MapStore)
m[env.DIYBackendLegacyLayout.Var().Name()] = value
return m
}
tests := []struct {
desc string
give map[string]string // files in the bucket
env env.MapStore // environment variables
want pulumiMeta
}{
{
// Empty bucket should be initialized to
// the current version by default.
desc: "empty",
want: pulumiMeta{Version: 1},
},
{
// Use legacy mode even for the new bucket
// because the environment variable is "1".
desc: "empty/legacy",
env: mkmap("1"),
want: pulumiMeta{Version: 0},
},
{
// Use legacy mode even for the new bucket
// because the environment variable is "true".
desc: "empty/legacy/true",
env: mkmap("true"),
want: pulumiMeta{Version: 0},
},
{
// Legacy mode is disabled by setting the env var
// to "false".
// This is also the default behavior.
desc: "empty/legacy/false",
env: mkmap("false"),
want: pulumiMeta{Version: 1},
},
{
// Non-empty bucket without a version file
// should get version 0 for legacy mode.
desc: "legacy",
give: map[string]string{
".pulumi/stacks/a.json": `{}`,
},
want: pulumiMeta{Version: 0},
},
{
desc: "version 0",
give: map[string]string{
".pulumi/meta.yaml": `version: 0`,
},
want: pulumiMeta{Version: 0},
},
{
// Non-empty bucket with a version file
// should get whatever is in the file.
desc: "version 1",
give: map[string]string{
".pulumi/meta.yaml": `version: 1`,
},
want: pulumiMeta{Version: 1},
},
{
desc: "future version",
give: map[string]string{
".pulumi/meta.yaml": `version: 42`,
},
want: pulumiMeta{Version: 42},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
b := memblob.OpenBucket(nil)
ctx := context.Background()
for name, body := range tt.give {
require.NoError(t, b.WriteAll(ctx, name, []byte(body), nil))
}
state, err := ensurePulumiMeta(ctx, b, env.NewEnv(tt.env))
require.NoError(t, err)
assert.Equal(t, &tt.want, state)
})
}
}
func TestEnsurePulumiMeta_corruption(t *testing.T) {
t.Parallel()
tests := []struct {
desc string
give string // contents of meta.yaml
wantErr string
}{
{
desc: "empty",
give: ``,
wantErr: `corrupt store: missing version in ".pulumi/meta.yaml"`,
},
{
desc: "other fields",
give: `foo: bar`,
wantErr: `corrupt store: missing version in ".pulumi/meta.yaml"`,
},
{
desc: "corrupt version",
give: `version: foo`,
wantErr: `corrupt store: unmarshal ".pulumi/meta.yaml"`,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
b := memblob.OpenBucket(nil)
ctx := context.Background()
require.NoError(t, b.WriteAll(ctx, ".pulumi/meta.yaml", []byte(tt.give), nil))
_, err := ensurePulumiMeta(context.Background(), b, env.NewEnv(nil))
assert.ErrorContains(t, err, tt.wantErr)
})
}
}
// Writes a metadata file to the bucket and reads it back.
func TestMeta_roundTrip(t *testing.T) {
t.Parallel()
tests := []struct {
desc string
give pulumiMeta
}{
{desc: "zero", give: pulumiMeta{Version: 0}},
{desc: "one", give: pulumiMeta{Version: 1}},
{desc: "future", give: pulumiMeta{Version: 42}},
}
for _, tt := range tests {
tt := tt
t.Run(tt.desc, func(t *testing.T) {
t.Parallel()
b := memblob.OpenBucket(nil)
// The bucket is always non-empty,
// so we won't automatically try to use version 1.
require.NoError(t,
b.WriteAll(context.Background(), ".pulumi/stacks/dev.json", []byte("bar"), nil))
ctx := context.Background()
require.NoError(t, tt.give.WriteTo(ctx, b))
got, err := ensurePulumiMeta(ctx, b, env.NewEnv(nil))
require.NoError(t, err)
assert.Equal(t, &tt.give, got)
})
}
}
// Verifies that we don't write a metadata file with version 0.
func TestMeta_WriteTo_zero(t *testing.T) {
t.Parallel()
tmpDir := t.TempDir()
bucket, err := fileblob.OpenBucket(tmpDir, nil)
require.NoError(t, err)
ctx := context.Background()
require.NoError(t, (&pulumiMeta{
Version: 0,
}).WriteTo(ctx, bucket))
assert.NoFileExists(t, filepath.Join(tmpDir, ".pulumi", "meta.yaml"))
}
// Verify that we don't create a metadata file with version 0 in buckets
// that have other files.
func TestNew_noMetaOnInit(t *testing.T) {
t.Parallel()
tmpDir := t.TempDir()
bucket, err := fileblob.OpenBucket(tmpDir, nil)
require.NoError(t, err)
require.NoError(t,
bucket.WriteAll(context.Background(), ".pulumi/stacks/dev.json", []byte("bar"), nil))
ctx := context.Background()
_, err = New(ctx, diagtest.LogSink(t), "file://"+filepath.ToSlash(tmpDir), nil)
require.NoError(t, err)
assert.NoFileExists(t, filepath.Join(tmpDir, ".pulumi", "meta.yaml"))
}