Skip to content

Commit

Permalink
Discard log messages when initializing the provider (#4650)
Browse files Browse the repository at this point in the history
Messages sent early to the "log" package end up being forwarded to
stderr, and Pulumi displays stderr by default to users, which is
undesirable.

Later in the provider life-cycle, Pulumi Terraform Bridge will reset
`log.SetOutput` again to capture and appropriately track diagnostic
logs, which should still work with this change.

Fixes #4645

A test is added to ensure we do not leak diagnostics again on a simple
program.
  • Loading branch information
t0yv0 authored Oct 17, 2024
1 parent 52bc53b commit 855caa5
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 0 deletions.
60 changes: 60 additions & 0 deletions provider/provider_nodejs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,66 @@ func TestRegress4568(t *testing.T) {
})
}

// Tests that there are no diagnostics by default on simple programs.
func TestNoExtranousLogOutput(t *testing.T) {
skipIfShort(t)
dir := filepath.Join("test-programs", "bucket-obj")
cwd, err := os.Getwd()
require.NoError(t, err)
providerName := "aws"
options := []opttest.Option{
opttest.LocalProviderPath(providerName, filepath.Join(cwd, "..", "bin")),
}
test := pulumitest.NewPulumiTest(t, dir, options...)
result := test.Preview(t)
assert.NotContainsf(t, result.StdOut, "Diagnostics:",
"No diagnostics should be emitted to stdout for simple programs")
assert.NotContainsf(t, result.StdErr, "Diagnostics:",
"No diagnostics should be emitted to stderr for simple programs")
}

// Since AWS is doing something non-standard with logging, double-check that `log.Printf` messages do get propagated
// when TF_LOG=DEBUG is set. One such message is set by aws.s3.Bucketv2 when refresh finds that the bucket no longer
// exists. Emulate this situation and assert that the message has propagated.
func TestUpstreamWarningsPropagated(t *testing.T) {
skipIfShort(t)
dir := filepath.Join("test-programs", "disappearing-bucket-object")
cwd, err := os.Getwd()
require.NoError(t, err)
providerName := "aws"
options := []opttest.Option{
opttest.LocalProviderPath(providerName, filepath.Join(cwd, "..", "bin")),
opttest.YarnLink("@pulumi/aws"),
opttest.Env("TF_LOG", "DEBUG"),
}
test := pulumitest.NewPulumiTest(t, dir, options...)

t.Logf("Creating the bucket object")
test.Up(t)

state := test.ExportStack(t)

t.Logf("Deleting the bucket object")
test.SetConfig(t, "bucket-object", "exclude")
test.Up(t)

t.Logf("Resetting the state back")
test.ImportStack(t, state)

t.Logf("Refreshing the stack and expecting bucket to be deleted from the state")
rr := test.Refresh(t)
t.Logf("%v%v", rr.StdOut, rr.StdErr)

// Upstream code has this line:
//
// log.Printf("[WARN] S3 Object (%s) not found, removing from state", d.Id())
//
assert.Containsf(t,
rr.StdErr+rr.StdOut,
"warning: S3 Object (index.ts) not found, removing from state",
"Expected upstream log.Printf to propagate under TF_LOG=DEBUG")
}

func getJSBaseOptions(t *testing.T) integration.ProgramTestOptions {
envRegion := getEnvRegion(t)
baseJS := integration.ProgramTestOptions{
Expand Down
2 changes: 2 additions & 0 deletions provider/test-programs/disappearing-bucket-object/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: disappearing-bucket-object
runtime: nodejs
13 changes: 13 additions & 0 deletions provider/test-programs/disappearing-bucket-object/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";

const cfg = new pulumi.Config();
const b = new aws.s3.BucketV2("my-bucket", {});

if (cfg.get("bucket-object") !== "exclude") {
const o = new aws.s3.BucketObjectv2("obj", {
bucket: b.bucket,
key: "index.ts",
source: new pulumi.asset.FileAsset("index.ts"),
});
}
15 changes: 15 additions & 0 deletions provider/test-programs/disappearing-bucket-object/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "disappearing-bucket-object",
"version": "0.1.0",
"license": "Apache-2.0",
"scripts": {
"build": "tsc"
},
"dependencies": {
"@pulumi/pulumi": "^3.0.0",
"@pulumi/aws": "^6.0.0"
},
"devDependencies": {
"@types/node": "^8.0.0"
}
}
18 changes: 18 additions & 0 deletions provider/test-programs/disappearing-bucket-object/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true,
"strictNullChecks": true
},
"files": [
"index.ts"
]
}
6 changes: 6 additions & 0 deletions provider/upstream_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ package provider

import (
"context"
"io"
"log"
"os"

awsShim "github.com/hashicorp/terraform-provider-aws/shim"
"github.com/pulumi/pulumi-aws/provider/v6/pkg/rds"
Expand All @@ -30,6 +33,9 @@ import (
// runtime startup is somewhat performance sensitive. Therefore any modifications undertaken here should complete
// quickly.
func newUpstreamProvider(ctx context.Context) awsShim.UpstreamProvider {
log.SetOutput(io.Discard) // ignore logging from upstream constructors
defer log.SetOutput(os.Stderr) // revert to default

upstreamProvider, err := awsShim.NewUpstreamProvider(ctx)
contract.AssertNoErrorf(err, "NewUpstreamProvider failed to initialize")
rds.ReconfigureResources(upstreamProvider.SDKV2Provider)
Expand Down

0 comments on commit 855caa5

Please sign in to comment.