161 lines
5.9 KiB
Go
161 lines
5.9 KiB
Go
// 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 containers
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/pulumi/pulumi/pkg/v2/testing/integration"
|
|
ptesting "github.com/pulumi/pulumi/sdk/v2/go/common/testing"
|
|
)
|
|
|
|
// TestPulumiDockerImage simulates building and running Pulumi programs on the pulumi/pulumi Docker image.
|
|
//
|
|
// NOTE: This test is intended to be run inside the aforementioned container, unlike the actions test below.
|
|
func TestPulumiDockerImage(t *testing.T) {
|
|
const stackOwner = "moolumi"
|
|
|
|
if os.Getenv("RUN_CONTAINER_TESTS") == "" {
|
|
t.Skip("Skipping container runtime tests because RUN_CONTAINER_TESTS not set.")
|
|
}
|
|
|
|
// Confirm we have credentials.
|
|
if os.Getenv("PULUMI_ACCESS_TOKEN") == "" {
|
|
t.Fatal("PULUMI_ACCESS_TOKEN not found, aborting tests.")
|
|
}
|
|
|
|
base := integration.ProgramTestOptions{
|
|
Tracing: "https://tracing.pulumi-engineering.com/collector/api/v1/spans",
|
|
ExpectRefreshChanges: true,
|
|
Quick: true,
|
|
SkipRefresh: true,
|
|
NoParallel: true, // we mark tests as Parallel manually when instantiating
|
|
}
|
|
|
|
for _, template := range []string{"csharp", "python", "typescript"} {
|
|
t.Run(template, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
e := ptesting.NewEnvironment(t)
|
|
defer func() {
|
|
e.RunCommand("pulumi", "stack", "rm", "--force", "--yes")
|
|
e.DeleteEnvironment()
|
|
}()
|
|
|
|
stackName := fmt.Sprintf("%s/container-%s-%x", stackOwner, template, time.Now().UnixNano())
|
|
e.RunCommand("pulumi", "new", template, "-y", "-f", "-s", stackName)
|
|
|
|
example := base.With(integration.ProgramTestOptions{
|
|
Dir: e.RootPath,
|
|
})
|
|
|
|
integration.ProgramTest(t, &example)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestPulumiActionsImage simulates building and running Pulumi programs on the pulumi/actions image.
|
|
//
|
|
// The main codepath being tested is the entrypoint script of the container, which contains logic for
|
|
// downloading dependencies, honoring various environment variables, etc.
|
|
func TestPulumiActionsImage(t *testing.T) {
|
|
const pulumiContainerToTest = "pulumi/actions:latest"
|
|
|
|
if os.Getenv("RUN_CONTAINER_TESTS") == "" {
|
|
t.Skip("Skipping container runtime tests because RUN_CONTAINER_TESTS not set.")
|
|
}
|
|
|
|
// Confirm we have credentials.
|
|
if os.Getenv("PULUMI_ACCESS_TOKEN") == "" {
|
|
t.Fatal("PULUMI_ACCESS_TOKEN not found, aborting tests.")
|
|
}
|
|
|
|
// MacOS workaround. os.TempDir returns a path under /var/, which isn't
|
|
// bindable in default Docker installs. So we override the behavior to
|
|
// use /tmp, which should work.
|
|
if strings.HasPrefix(os.TempDir(), "/var/") {
|
|
os.Setenv("TMPDIR", "/tmp")
|
|
}
|
|
|
|
// Confirm the container has been built, will emit no output if it isn't found.
|
|
e := ptesting.NewEnvironment(t)
|
|
stdout, _ := e.RunCommand("docker", "images", pulumiContainerToTest, "--quiet")
|
|
if len(stdout) == 0 {
|
|
t.Fatalf("It doesn't appear that the container image %s has been built.", pulumiContainerToTest)
|
|
}
|
|
e.DeleteEnvironment()
|
|
|
|
t.Run("dotnet", func(t *testing.T) {
|
|
testRuntimeWorksInContainer(t, "dotnet", pulumiContainerToTest)
|
|
})
|
|
|
|
t.Run("nodejs", func(t *testing.T) {
|
|
testRuntimeWorksInContainer(t, "nodejs", pulumiContainerToTest)
|
|
})
|
|
|
|
t.Run("python", func(t *testing.T) {
|
|
testRuntimeWorksInContainer(t, "python", pulumiContainerToTest)
|
|
})
|
|
}
|
|
|
|
// testRuntimeWorksInContainer runs a test that attempts to run a Pulumi program in the given
|
|
// container. It is assumed that Pulumi program has a configuration key named "runtime" and
|
|
// will print "Hello from {{ runtime }}".
|
|
func testRuntimeWorksInContainer(t *testing.T, runtime, container string) {
|
|
const stackOwner = "moolumi"
|
|
|
|
stackName := fmt.Sprintf("%s/container-%s-%x", stackOwner, runtime, time.Now().UnixNano())
|
|
|
|
e := ptesting.NewEnvironment(t)
|
|
defer func() {
|
|
e.RunCommand("pulumi", "stack", "rm", "--force", "--yes")
|
|
// BUG: We mount /tmp/${e.CWD} into the container, which contains the Pulumi program,
|
|
// and then the container executes and leaves new files there too. Since code in the
|
|
// container ( by default) runs as root (at least that's the default behavior on Linux),
|
|
// then on CI we don't have access to call e.DeleteEnvironment(). (Since files created
|
|
// on the container are owned by "root root".) We should fix this, since as-is we
|
|
// are leaving crap in the temp folder.
|
|
t.Logf("NOTE: Skipping cleanup of test environment. Leaving files in %q", e.CWD)
|
|
}()
|
|
e.ImportDirectory(runtime)
|
|
|
|
// Create the stack and set the required configuration.
|
|
e.RunCommand("pulumi", "stack", "init", stackName)
|
|
e.RunCommand("pulumi", "config", "set", "runtime", runtime)
|
|
|
|
// Run `pulumi up` using the Pulumi container.
|
|
stdout, _ := e.RunCommand("docker", "run",
|
|
// Set the PULUMI_ACCESS_TOKEN environment variable, to authenticate.
|
|
// BUG: This is why the these tests aren't configured to run as part of CI,
|
|
// since the access token would get written to logs.
|
|
"--env", fmt.Sprintf("PULUMI_ACCESS_TOKEN=%s", os.Getenv("PULUMI_ACCESS_TOKEN")),
|
|
// Mount the stack's source code into the container.
|
|
"--volume", fmt.Sprintf("%s:/src", e.CWD),
|
|
// Set working directory when running the container.
|
|
"--workdir", "/src",
|
|
// Cleanup the container on shutdown.
|
|
"--rm",
|
|
// Container to run.
|
|
container,
|
|
// Flags to the container's entry point (`pulumi`).
|
|
"up", "--stack", stackName, "--yes")
|
|
|
|
assert.Contains(t, stdout, "Hello from "+runtime,
|
|
"Looking for indication stack update was successful in container output.")
|
|
}
|