mirror of https://github.com/pulumi/pulumi.git
280 lines
7.6 KiB
Go
280 lines
7.6 KiB
Go
package cli
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io/ioutil"
|
|
"testing"
|
|
|
|
"github.com/blang/semver"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v2/backend"
|
|
"github.com/pulumi/pulumi/pkg/v2/backend/display"
|
|
backend_test "github.com/pulumi/pulumi/pkg/v2/backend/testing"
|
|
"github.com/pulumi/pulumi/pkg/v2/engine"
|
|
"github.com/pulumi/pulumi/pkg/v2/resource/deploy"
|
|
"github.com/pulumi/pulumi/pkg/v2/resource/deploy/deploytest"
|
|
"github.com/pulumi/pulumi/pkg/v2/secrets/b64"
|
|
"github.com/pulumi/pulumi/pkg/v2/util/cancel"
|
|
"github.com/pulumi/pulumi/sdk/v2/go/common/diag"
|
|
"github.com/pulumi/pulumi/sdk/v2/go/common/diag/colors"
|
|
"github.com/pulumi/pulumi/sdk/v2/go/common/resource/plugin"
|
|
"github.com/pulumi/pulumi/sdk/v2/go/common/workspace"
|
|
)
|
|
|
|
var defaultProject = &workspace.Project{
|
|
Name: "project",
|
|
}
|
|
|
|
func testStack(owner, project, stack string) *backend_test.Stack {
|
|
return &backend_test.Stack{
|
|
ID: backend.StackIdentifier{
|
|
Owner: owner,
|
|
Project: project,
|
|
Stack: stack,
|
|
},
|
|
}
|
|
}
|
|
|
|
func newClient(stacks ...*backend_test.Stack) *backend_test.Client {
|
|
return backend_test.NewClient(backend_test.ClientConfig{
|
|
Name: "test",
|
|
User: "user",
|
|
}, stacks...)
|
|
}
|
|
|
|
func newBackend(client *backend_test.Client, project *workspace.Project) *Backend {
|
|
return &Backend{
|
|
d: diag.DefaultSink(ioutil.Discard, ioutil.Discard, diag.FormatOptions{Color: colors.Never}),
|
|
currentProject: project,
|
|
client: client,
|
|
}
|
|
}
|
|
|
|
type cancellationScopeSource int
|
|
|
|
func (cancellationScopeSource) NewScope(events chan<- engine.Event, isPreview bool) CancellationScope {
|
|
cancelContext, _ := cancel.NewContext(context.Background())
|
|
return &cancellationScope{context: cancelContext}
|
|
}
|
|
|
|
type cancellationScope struct {
|
|
context *cancel.Context
|
|
}
|
|
|
|
func (s *cancellationScope) Context() *cancel.Context {
|
|
return s.context
|
|
}
|
|
|
|
func (s *cancellationScope) Close() {
|
|
}
|
|
|
|
func TestCreateStack(t *testing.T) {
|
|
stackID := backend.StackIdentifier{
|
|
Owner: "user",
|
|
Project: "project",
|
|
Stack: "stack",
|
|
}
|
|
|
|
client := newClient()
|
|
b := newBackend(client, defaultProject)
|
|
|
|
_, err := b.CreateStack(context.Background(), stackID)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Len(t, client.Stacks, 1)
|
|
}
|
|
|
|
func TestListStacks(t *testing.T) {
|
|
client := newClient(
|
|
testStack("user", "project", "stack"),
|
|
testStack("user", "project", "stack2"),
|
|
testStack("user", "project2", "stack"))
|
|
b := newBackend(client, defaultProject)
|
|
|
|
stacks, err := b.ListStacks(context.Background(), backend.ListStacksFilter{})
|
|
assert.NoError(t, err)
|
|
assert.Len(t, stacks, 3)
|
|
|
|
projectName := "project"
|
|
stacks, err = b.ListStacks(context.Background(), backend.ListStacksFilter{Project: &projectName})
|
|
assert.NoError(t, err)
|
|
assert.Len(t, stacks, 2)
|
|
}
|
|
|
|
func TestGetStack(t *testing.T) {
|
|
client := newClient(testStack("user", "project", "stack"))
|
|
b := newBackend(client, defaultProject)
|
|
|
|
s, err := b.GetStack(context.Background(), backend.StackIdentifier{
|
|
Owner: "user",
|
|
Project: "project",
|
|
Stack: "stack",
|
|
})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, s)
|
|
|
|
s, err = b.GetStack(context.Background(), backend.StackIdentifier{
|
|
Owner: "user",
|
|
Project: "project",
|
|
Stack: "stack2",
|
|
})
|
|
assert.NoError(t, err)
|
|
assert.Nil(t, s)
|
|
}
|
|
|
|
func TestRemoveStack(t *testing.T) {
|
|
client := newClient(testStack("user", "project", "stack"))
|
|
b := newBackend(client, defaultProject)
|
|
|
|
s, err := b.GetStack(context.Background(), backend.StackIdentifier{
|
|
Owner: "user",
|
|
Project: "project",
|
|
Stack: "stack",
|
|
})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, s)
|
|
|
|
_, err = b.RemoveStack(context.Background(), s, false)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, client.Stacks, 0)
|
|
}
|
|
|
|
func TestRenameStack(t *testing.T) {
|
|
client := newClient(testStack("user", "project", "stack"))
|
|
b := newBackend(client, defaultProject)
|
|
|
|
s, err := b.GetStack(context.Background(), backend.StackIdentifier{
|
|
Owner: "user",
|
|
Project: "project",
|
|
Stack: "stack",
|
|
})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, s)
|
|
|
|
newID, err := b.RenameStack(context.Background(), s, "user/project/stack2")
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, backend.StackIdentifier{
|
|
Owner: "user",
|
|
Project: "project",
|
|
Stack: "stack2",
|
|
}, newID)
|
|
|
|
_, err = b.RenameStack(context.Background(), s, "user2/project/stack2")
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "does not match existing owner")
|
|
}
|
|
|
|
func TestPreview(t *testing.T) {
|
|
loaders := []*deploytest.ProviderLoader{
|
|
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
|
|
return &deploytest.Provider{}, nil
|
|
}),
|
|
}
|
|
|
|
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
|
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true)
|
|
assert.NoError(t, err)
|
|
return nil
|
|
})
|
|
host := deploytest.NewPluginHost(nil, nil, program, loaders...)
|
|
|
|
client := newClient(testStack("user", "project", "stack"))
|
|
b := newBackend(client, defaultProject)
|
|
|
|
s, err := b.GetStack(context.Background(), backend.StackIdentifier{
|
|
Owner: "user",
|
|
Project: "project",
|
|
Stack: "stack",
|
|
})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, s)
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
changes, res := s.Preview(context.Background(), UpdateOperation{
|
|
Proj: defaultProject,
|
|
M: &UpdateMetadata{},
|
|
Opts: UpdateOptions{
|
|
Engine: engine.UpdateOptions{Host: host},
|
|
Display: display.Options{
|
|
Color: colors.Never,
|
|
Stdout: &stdout,
|
|
Stderr: &stderr,
|
|
},
|
|
},
|
|
SecretsManager: b64.NewBase64SecretsManager(),
|
|
Scopes: cancellationScopeSource(0),
|
|
})
|
|
assert.Nil(t, res)
|
|
assert.Equal(t, engine.ResourceChanges{
|
|
deploy.OpCreate: 1,
|
|
}, changes)
|
|
|
|
stdoutText := stdout.String()
|
|
assert.Contains(t, stdoutText, "+ pkgA:m:typA resA create")
|
|
assert.Contains(t, stdoutText, "pulumi:pulumi:Stack project-stack")
|
|
assert.Contains(t, stdoutText, "+ 1 to create")
|
|
|
|
updates, err := b.GetHistory(context.Background(), s.ID())
|
|
assert.NoError(t, err)
|
|
assert.Len(t, updates, 0)
|
|
}
|
|
|
|
func TestUpdate(t *testing.T) {
|
|
loaders := []*deploytest.ProviderLoader{
|
|
deploytest.NewProviderLoader("pkgA", semver.MustParse("1.0.0"), func() (plugin.Provider, error) {
|
|
return &deploytest.Provider{}, nil
|
|
}),
|
|
}
|
|
|
|
program := deploytest.NewLanguageRuntime(func(_ plugin.RunInfo, monitor *deploytest.ResourceMonitor) error {
|
|
_, _, _, err := monitor.RegisterResource("pkgA:m:typA", "resA", true)
|
|
assert.NoError(t, err)
|
|
return nil
|
|
})
|
|
host := deploytest.NewPluginHost(nil, nil, program, loaders...)
|
|
|
|
client := newClient(testStack("user", "project", "stack"))
|
|
b := newBackend(client, defaultProject)
|
|
|
|
s, err := b.GetStack(context.Background(), backend.StackIdentifier{
|
|
Owner: "user",
|
|
Project: "project",
|
|
Stack: "stack",
|
|
})
|
|
assert.NoError(t, err)
|
|
assert.NotNil(t, s)
|
|
|
|
var stdout, stderr bytes.Buffer
|
|
changes, res := s.Update(context.Background(), UpdateOperation{
|
|
Proj: defaultProject,
|
|
M: &UpdateMetadata{},
|
|
Opts: UpdateOptions{
|
|
SkipPreview: true,
|
|
Engine: engine.UpdateOptions{Host: host},
|
|
Display: display.Options{
|
|
Color: colors.Never,
|
|
Stdout: &stdout,
|
|
Stderr: &stderr,
|
|
},
|
|
},
|
|
SecretsManager: b64.NewBase64SecretsManager(),
|
|
Scopes: cancellationScopeSource(0),
|
|
})
|
|
assert.Nil(t, res)
|
|
assert.Equal(t, engine.ResourceChanges{
|
|
deploy.OpCreate: 1,
|
|
}, changes)
|
|
|
|
stdoutText := stdout.String()
|
|
assert.Contains(t, stdoutText, "+ pkgA:m:typA resA creating")
|
|
assert.Contains(t, stdoutText, "+ pkgA:m:typA resA created")
|
|
assert.Contains(t, stdoutText, "pulumi:pulumi:Stack project-stack")
|
|
assert.Contains(t, stdoutText, "+ 1 created")
|
|
|
|
updates, err := b.GetHistory(context.Background(), s.ID())
|
|
assert.NoError(t, err)
|
|
assert.Len(t, updates, 1)
|
|
}
|