Skip to content

Commit

Permalink
Enable preview for create and update
Browse files Browse the repository at this point in the history
Currently if you update a resource, all outputs are shown as computed
during preview. This means that downstream resources might show a
replacement in the plan if they are using one of those output values.

There are some outputs that we know will not change unless the resource
is replaced (I'm referring to these as "stable" outputs). For stable
outputs we can copy the value from the state in order to show an
accurate preview.

The problem is that the CCAPI schema has no way of determining
programmatically which outputs are stable and which are not. Because of
this, this PR introduces a heuristic to determine if an output is a
stable output.

- Is the value a `readOnlyProperty` in the schema? This indicates that
  it is a computed output property
- Is the property the resource `id`, `arn` or `name`? If the id, arn, or
  name is a computed property then we can assume that it is a stable
  property. I don't know of any cases where these change outside of a
  resource replacement.

This is not 100% coverage of stable properties, but it should get us
most of the impactful properties. To get close to 100% coverage we will
probably need a schema overlay where we can contribute to mapping these
stable properties for each resource.

closes #1141
  • Loading branch information
corymhall committed Dec 6, 2024
1 parent 45ae4f6 commit c2f761c
Show file tree
Hide file tree
Showing 16 changed files with 9,261 additions and 5 deletions.
28 changes: 25 additions & 3 deletions examples/examples_nodejs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ func TestGetTs(t *testing.T) {
integration.ProgramTest(t, &test)
}

func TestPreviewStableProperties(t *testing.T) {
cwd := getCwd(t)
options := []opttest.Option{
opttest.LocalProviderPath("aws-native", filepath.Join(cwd, "..", "bin")),
opttest.YarnLink("@pulumi/aws-native"),
}
test := pulumitest.NewPulumiTest(t, filepath.Join(cwd, "stable-outputs-preview"), options...)
test.SetConfig(t, "lambdaDescription", "Lambda 1")
defer func() {
test.Destroy(t)
}()

upResult := test.Up(t)
t.Logf("#%v", upResult.Summary)

// updating a non-replaceOnChanges property to ensure
// that the downstream resources doesn't show a replacement
test.SetConfig(t, "lambdaDescription", "Lambda 2")
previewResult := test.Preview(t)
assertpreview.HasNoReplacements(t, previewResult)
}

func TestCustomResourceEmulator(t *testing.T) {
crossTest := func(t *testing.T, outputs auto.OutputMap) {
require.Contains(t, outputs, "cloudformationAmiId")
Expand Down Expand Up @@ -146,10 +168,10 @@ func TestAutoNamingOverlay(t *testing.T) {
var buf bytes.Buffer
test := getJSBaseOptions(t).
With(integration.ProgramTestOptions{
Dir: filepath.Join(getCwd(t), "autonaming-overlay"),
Stderr: &buf,
Dir: filepath.Join(getCwd(t), "autonaming-overlay"),
Stderr: &buf,
Config: map[string]string{
"roleName": "myReallyLongRoleNameThatIsLongerThan64CharactersOneTwoThreeFour",
"roleName": "myReallyLongRoleNameThatIsLongerThan64CharactersOneTwoThreeFour",
},
ExpectFailure: true,
ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
Expand Down
3 changes: 3 additions & 0 deletions examples/stable-outputs-preview/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/bin/
/node_modules/
handler.zip
3 changes: 3 additions & 0 deletions examples/stable-outputs-preview/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: aws-native-stable-outputs-preview
runtime: nodejs
description: An example program to test stable outputs during preview
8 changes: 8 additions & 0 deletions examples/stable-outputs-preview/app/index.handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const handler = async () => {
return {
statusCode: 200,
body: JSON.stringify({
message: "Hello World!",
}),
};
};
49 changes: 49 additions & 0 deletions examples/stable-outputs-preview/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as pulumi from '@pulumi/pulumi';
import * as path from 'path';
import * as ccapi from "@pulumi/aws-native";
import * as aws from '@pulumi/aws';
import { zipDirectory } from './zip';

const config = new pulumi.Config();
const desc = config.get('lambdaDescription') ?? 'test lambda';
const role = new ccapi.iam.Role('lambda-role', {
assumeRolePolicyDocument: {
Version: "2012-10-17",
Statement: [
{
Effect: "Allow",
Principal: {
Service: "lambda.amazonaws.com",
},
Action: "sts:AssumeRole",
},
],
},
});


const bucket = new ccapi.s3.Bucket('bucket');
const object = new aws.s3.BucketObjectv2(
'object',
{
source: zipDirectory(path.join(__dirname, 'app'), 'handler.zip'),
bucket: bucket.bucketName.apply(bucket => bucket!),
key: 'handler.zip',
},
);
const handler = new ccapi.lambda.Function('my-function', {
code: {
s3Bucket: bucket.bucketName.apply(bucket => bucket!),
s3Key: object.key,
},
description: desc,
runtime: 'nodejs20.x',
handler: 'index.handler',
role: role.arn,
});

new ccapi.lambda.Permission('chall-permission', {
functionName: handler.arn,
action: 'lambda:InvokeFunction',
principal: 's3.amazonaws.com',
});
Loading

0 comments on commit c2f761c

Please sign in to comment.