pulumi/tests/integration/integration_acceptance_test.go

188 lines
6.1 KiB
Go

// Copyright 2016-2022, 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.
//go:build all
package ints
import (
"bytes"
"path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/pulumi/pulumi/pkg/v3/testing/integration"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource/config"
ptesting "github.com/pulumi/pulumi/sdk/v3/go/common/testing"
"github.com/pulumi/pulumi/sdk/v3/go/common/workspace"
)
// TestConfigSave ensures that config commands in the Pulumi CLI work as expected.
func TestConfigSave(t *testing.T) {
t.Parallel()
e := ptesting.NewEnvironment(t)
defer e.DeleteIfNotFailed()
// Initialize an empty stack.
path := filepath.Join(e.RootPath, "Pulumi.yaml")
project := workspace.Project{
Name: "testing-config",
Runtime: workspace.NewProjectRuntimeInfo("nodejs", nil),
}
err := project.Save(path)
assert.NoError(t, err)
e.RunCommand("pulumi", "login", "--cloud-url", e.LocalURL())
e.RunCommand("pulumi", "stack", "init", "testing-2")
e.RunCommand("pulumi", "stack", "init", "testing-1")
// Now configure and save a few different things:
e.RunCommand("pulumi", "config", "set", "configA", "value1")
e.RunCommand("pulumi", "config", "set", "configB", "value2", "--stack", "testing-2")
e.RunCommand("pulumi", "stack", "select", "testing-2")
e.RunCommand("pulumi", "config", "set", "configD", "value4")
e.RunCommand("pulumi", "config", "set", "configC", "value3", "--stack", "testing-1")
// Now read back the config using the CLI:
{
stdout, _ := e.RunCommand("pulumi", "config", "get", "configB")
assert.Equal(t, "value2\n", stdout)
}
{
// the config in a different stack, so this should error.
stdout, stderr := e.RunCommandExpectError("pulumi", "config", "get", "configA")
assert.Equal(t, "", stdout)
assert.NotEqual(t, "", stderr)
}
{
// but selecting the stack should let you see it
stdout, _ := e.RunCommand("pulumi", "config", "get", "configA", "--stack", "testing-1")
assert.Equal(t, "value1\n", stdout)
}
// Finally, check that the stack file contains what we expected.
validate := func(k string, v string, cfg config.Map) {
key, err := config.ParseKey("testing-config:config:" + k)
assert.NoError(t, err)
d, ok := cfg[key]
assert.True(t, ok, "config key %v should be set", k)
dv, err := d.Value(nil)
assert.NoError(t, err)
assert.Equal(t, v, dv)
}
testStack1, err := workspace.LoadProjectStack(&project, filepath.Join(e.CWD, "Pulumi.testing-1.yaml"))
assert.NoError(t, err)
testStack2, err := workspace.LoadProjectStack(&project, filepath.Join(e.CWD, "Pulumi.testing-2.yaml"))
assert.NoError(t, err)
assert.Equal(t, 2, len(testStack1.Config))
assert.Equal(t, 2, len(testStack2.Config))
validate("configA", "value1", testStack1.Config)
validate("configC", "value3", testStack1.Config)
validate("configB", "value2", testStack2.Config)
validate("configD", "value4", testStack2.Config)
e.RunCommand("pulumi", "stack", "rm", "--yes")
}
func TestRotatePassphrase(t *testing.T) {
t.Parallel()
e := ptesting.NewEnvironment(t)
defer e.DeleteIfNotFailed()
e.ImportDirectory("rotate_passphrase")
e.RunCommand("pulumi", "login", "--cloud-url", e.LocalURL())
e.RunCommand("pulumi", "stack", "init", "dev")
e.RunCommand("pulumi", "up", "--skip-preview", "--yes")
e.RunCommand("pulumi", "config", "set", "--secret", "foo", "bar")
e.SetEnvVars("PULUMI_TEST_PASSPHRASE=true")
e.Stdin = strings.NewReader("qwerty\nqwerty\n")
e.RunCommand("pulumi", "stack", "change-secrets-provider", "passphrase")
e.Stdin, e.Passphrase = nil, "qwerty"
e.RunCommand("pulumi", "config", "get", "foo")
}
//nolint:paralleltest // uses parallel programtest
func TestJSONOutputWithStreamingPreview(t *testing.T) {
stdout := &bytes.Buffer{}
// Test with env var for streaming preview (should *not* print previewSummary).
integration.ProgramTest(t, &integration.ProgramTestOptions{
Dir: filepath.Join("stack_outputs", "nodejs"),
Dependencies: []string{"@pulumi/pulumi"},
Stdout: stdout,
Verbose: true,
JSONOutput: true,
Env: []string{"PULUMI_ENABLE_STREAMING_JSON_PREVIEW=1"},
ExtraRuntimeValidation: func(t *testing.T, stack integration.RuntimeValidationStackInfo) {
output := stdout.String()
// Check that the previewSummary is *not* present.
assert.NotRegexp(t, previewSummaryRegex, output)
// Check that each event present in the event stream is also in stdout.
for _, evt := range stack.Events {
assertOutputContainsEvent(t, evt, output)
}
},
})
}
func TestPassphrasePrompting(t *testing.T) {
t.Parallel()
e := ptesting.NewEnvironment(t)
defer e.DeleteIfNotFailed()
e.NoPassphrase = true
// Setting PULUMI_TEST_PASSPHRASE allows prompting (reading from stdin)
// even though the test won't be interactive.
e.SetEnvVars("PULUMI_TEST_PASSPHRASE=true")
e.RunCommand("pulumi", "login", "--cloud-url", e.LocalURL())
e.Stdin = strings.NewReader("qwerty\nqwerty\n")
e.RunCommand("pulumi", "new", "go",
"--name", "pphraseprompt",
"--description", "A project that tests passphrase prompts",
"--stack", "dev",
"--secrets-provider", "passphrase",
"--yes",
"--force")
e.Stdin = strings.NewReader("qwerty\n")
e.RunCommand("pulumi", "up", "--stack", "dev", "--skip-preview", "--yes")
e.Stdin = strings.NewReader("qwerty\n")
e.RunCommand("pulumi", "stack", "export", "--stack", "dev", "--file", "stack.json")
e.Stdin = strings.NewReader("qwerty\n")
e.RunCommand("pulumi", "stack", "import", "--stack", "dev", "--file", "stack.json")
e.Stdin = strings.NewReader("qwerty\n")
e.RunCommand("pulumi", "destroy", "--stack", "dev", "--skip-preview", "--yes")
}