Do not diff __internal property in DiffConfig (#414)

This PR updates the implementation of DiffConfig to remove the
`__internal` property when comparing provider config between old state
and new input. It is observed that the `__internal` property is present
when a default provider is used. This causes a provider replacement
every time a user upgrades pulumi-docker-build, as the `__internal`
property is always stripped from state, so Pulumi will always report a
diff.

Ideally, we should determine if this bug can be fixed in either upstream
pulumi-go-provider or pulumi itself. For now, we will fix this locally
within pulumi-docker-build to unblock our users.

Changes:

- Update DiffConfig implementation to strip `__internal` property from
new inputs.
- Add a nodejs upgrade test to test that this solution works

Fixes: #404
This commit is contained in:
Ramon Quitales
2025-01-14 15:01:51 -08:00
committed by GitHub
parent 8025c5f938
commit d46882f9eb
9 changed files with 214 additions and 1 deletions

View File

@@ -12,6 +12,7 @@
### Fixed
- Custom `# syntax=` directives no longer cause validation errors. (https://github.com/pulumi/pulumi-docker-build/issues/300)
- Upgrading docker-build no longer causes resource replacements. (https://github.com/pulumi/pulumi-docker-build/issues/404)
## 0.0.7 (2024-10-16)

View File

@@ -9,12 +9,18 @@ import (
"math/rand"
"os"
"path"
"path/filepath"
"strings"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ecr"
"github.com/pulumi/providertest"
"github.com/pulumi/providertest/optproviderupgrade"
"github.com/pulumi/providertest/pulumitest"
"github.com/pulumi/providertest/pulumitest/assertpreview"
"github.com/pulumi/providertest/pulumitest/opttest"
"github.com/pulumi/pulumi/pkg/v3/testing/integration"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -35,6 +41,30 @@ func TestNodeExample(t *testing.T) {
integration.ProgramTest(t, &test)
}
func TestNodeExampleUpgrade(t *testing.T) {
t.Parallel()
var (
providerName string = "docker-build"
baselineVersion string = "0.0.7"
)
cwd, err := os.Getwd()
require.NoError(t, err)
options := []opttest.Option{
opttest.DownloadProviderVersion(providerName, baselineVersion),
opttest.LocalProviderPath(providerName, filepath.Join(cwd, "..", "bin")),
opttest.YarnLink("@pulumi/docker-build"),
opttest.TestInPlace(),
}
test := pulumitest.NewPulumiTest(t, filepath.Join(cwd, "upgrade-node"), options...)
result := providertest.PreviewProviderUpgrade(t, test, providerName, baselineVersion,
optproviderupgrade.DisableAttach())
assertpreview.HasNoReplacements(t, result)
}
// TestCaching simulates a slow build with --cache-to enabled. We aren't able
// to directly detect cache hits, so we re-run the update and confirm it took
// less time than the image originally took to build.

View File

@@ -0,0 +1,20 @@
{"method":"/pulumirpc.LanguageRuntime/GetPluginInfo","request":{},"response":{"version":"3.145.0-dev.0"}}
{"method":"/pulumirpc.LanguageRuntime/GetRequiredPackages","request":{"info":{"entryPoint":".","options":{},"programDirectory":"/private/var/folders/xl/bqjwsf01315fs4yp20dj3x640000gn/T/TestNodeExampleUpgrade4279645683/006/upgrade-node","rootDirectory":"/private/var/folders/xl/bqjwsf01315fs4yp20dj3x640000gn/T/TestNodeExampleUpgrade4279645683/006/upgrade-node"}},"response":{"packages":[{"kind":"resource","name":"docker-build","version":"v0.1.0-alpha.0+dev"}]}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"transforms"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"deletedWith"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"invokeTransforms"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"resourceReferences"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"aliasSpecs"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"secrets"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"parameterization"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"outputValues"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/RegisterResource","request":{"acceptResources":true,"acceptSecrets":true,"aliasSpecs":true,"customTimeouts":{},"name":"provider-docker-build-test","object":{},"sourcePosition":{"column":23,"line":38,"uri":"file:///private/var/folders/xl/bqjwsf01315fs4yp20dj3x640000gn/T/TestNodeExampleUpgrade4279645683/006/upgrade-node/node_modules/@pulumi/runtime/stack.ts"},"supportsPartialValues":true,"supportsResultReporting":true,"type":"pulumi:pulumi:Stack"},"response":{"object":{},"urn":"urn:pulumi:test::provider-docker-build::pulumi:pulumi:Stack::provider-docker-build-test"}}
{"method":"/pulumirpc.ResourceMonitor/RegisterResourceOutputs","request":{"outputs":{},"urn":"urn:pulumi:test::provider-docker-build::pulumi:pulumi:Stack::provider-docker-build-test"},"response":{}}
{"method":"/pulumirpc.ResourceProvider/Handshake","request":{"engineAddress":"127.0.0.1:56051","programDirectory":"/Users/rquitales/.pulumi/plugins/resource-docker-build-v0.0.7","rootDirectory":"/Users/rquitales/.pulumi/plugins/resource-docker-build-v0.0.7"}}
{"method":"/pulumirpc.ResourceProvider/GetPluginInfo","request":{},"response":{"version":"v0.0.7"}}
{"method":"/pulumirpc.ResourceProvider/CheckConfig","request":{"name":"default_0_1_0_alpha_0_dev","news":{"version":"0.1.0-alpha.0+dev"},"olds":{},"type":"pulumi:providers:docker-build","urn":"urn:pulumi:test::provider-docker-build::pulumi:providers:docker-build::default_0_1_0_alpha_0_dev"},"response":{"inputs":{"host":""}}}
{"method":"/pulumirpc.ResourceProvider/Configure","request":{"acceptResources":true,"acceptSecrets":true,"args":{"host":""},"sendsOldInputs":true,"sendsOldInputsToDelete":true,"variables":{"docker-build:config:host":""}},"response":{"acceptOutputs":true,"acceptResources":true,"acceptSecrets":true,"supportsPreview":true}}
{"method":"/pulumirpc.ResourceProvider/Check","request":{"name":"inline","news":{"buildOnPreview":true,"dockerfile":{"inline":"FROM alpine\nRUN echo \"This uses an inline Dockerfile! 👍\"\n"},"network":"default","push":false},"olds":{},"randomSeed":"gfcHtIMoX4qpk2cxRceOJcYDaSsHyPNBhhd8lYTFcqw=","type":"docker-build:index:Image","urn":"urn:pulumi:test::provider-docker-build::docker-build:index:Image::inline"},"response":{"inputs":{"buildOnPreview":true,"context":{"location":"."},"dockerfile":{"inline":"FROM alpine\nRUN echo \"This uses an inline Dockerfile! 👍\"\n","location":""},"exec":false,"load":false,"network":"default","noCache":false,"pull":false,"push":false,"target":""}}}
{"method":"/pulumirpc.ResourceProvider/Create","request":{"name":"inline","properties":{"buildOnPreview":true,"context":{"location":"."},"dockerfile":{"inline":"FROM alpine\nRUN echo \"This uses an inline Dockerfile! 👍\"\n","location":""},"exec":false,"load":false,"network":"default","noCache":false,"pull":false,"push":false,"target":""},"type":"docker-build:index:Image","urn":"urn:pulumi:test::provider-docker-build::docker-build:index:Image::inline"},"response":{"id":"inline","properties":{"buildOnPreview":true,"context":{"location":"."},"contextHash":"a9db789a55c8ad91fe04e176aefcf0b74f86636ae12e7cd475421416672da8c1","digest":"","dockerfile":{"inline":"FROM alpine\nRUN echo \"This uses an inline Dockerfile! 👍\"\n","location":""},"exec":false,"load":false,"network":"default","noCache":false,"pull":false,"push":false,"ref":"","target":""}}}
{"method":"/pulumirpc.ResourceMonitor/RegisterResource","request":{"acceptResources":true,"acceptSecrets":true,"aliasSpecs":true,"custom":true,"customTimeouts":{},"name":"inline","object":{"buildOnPreview":true,"dockerfile":{"inline":"FROM alpine\nRUN echo \"This uses an inline Dockerfile! 👍\"\n"},"network":"default","push":false},"parent":"urn:pulumi:test::provider-docker-build::pulumi:pulumi:Stack::provider-docker-build-test","propertyDependencies":{"buildOnPreview":{},"dockerfile":{},"network":{},"push":{}},"sourcePosition":{"column":16,"line":4,"uri":"file:///private/var/folders/xl/bqjwsf01315fs4yp20dj3x640000gn/T/TestNodeExampleUpgrade4279645683/006/upgrade-node/index.ts"},"supportsPartialValues":true,"supportsResultReporting":true,"type":"docker-build:index:Image","version":"0.1.0-alpha.0+dev"},"response":{"id":"inline","object":{"buildOnPreview":true,"context":{"location":"."},"contextHash":"a9db789a55c8ad91fe04e176aefcf0b74f86636ae12e7cd475421416672da8c1","digest":"","dockerfile":{"inline":"FROM alpine\nRUN echo \"This uses an inline Dockerfile! 👍\"\n","location":""},"exec":false,"load":false,"network":"default","noCache":false,"pull":false,"push":false,"ref":"","target":""},"urn":"urn:pulumi:test::provider-docker-build::docker-build:index:Image::inline"}}
{"method":"/pulumirpc.LanguageRuntime/Run","request":{"configPropertyMap":{},"info":{"entryPoint":".","options":{},"programDirectory":"/private/var/folders/xl/bqjwsf01315fs4yp20dj3x640000gn/T/TestNodeExampleUpgrade4279645683/006/upgrade-node","rootDirectory":"/private/var/folders/xl/bqjwsf01315fs4yp20dj3x640000gn/T/TestNodeExampleUpgrade4279645683/006/upgrade-node"},"loaderTarget":"127.0.0.1:56055","monitorAddress":"127.0.0.1:56054","organization":"organization","parallel":40,"program":".","project":"provider-docker-build","pwd":"/private/var/folders/xl/bqjwsf01315fs4yp20dj3x640000gn/T/TestNodeExampleUpgrade4279645683/006/upgrade-node","stack":"test"},"response":{}}

View File

@@ -0,0 +1,96 @@
{
"version": 3,
"deployment": {
"manifest": {
"time": "2025-01-14T12:40:32.429451-08:00",
"magic": "7c53c69df7094e39d5562ed2abf1e12099c2c54a7b9b411faca1dcb7ec1fef8a",
"version": "v3.145.0"
},
"secrets_providers": {
"type": "passphrase",
"state": {
"salt": "v1:EuqbHY9lEXg=:v1:xNv8Pt7D2Pf/iDkg:tOvHbUIXPITf+BgbbjqPZaWIqKD8jQ=="
}
},
"resources": [
{
"urn": "urn:pulumi:test::provider-docker-build::pulumi:pulumi:Stack::provider-docker-build-test",
"custom": false,
"type": "pulumi:pulumi:Stack",
"created": "2025-01-14T20:40:27.082534Z",
"modified": "2025-01-14T20:40:27.082534Z",
"sourcePosition": "project:///node_modules/@pulumi/runtime/stack.ts#38,23"
},
{
"urn": "urn:pulumi:test::provider-docker-build::pulumi:providers:docker-build::default_0_1_0_alpha_0_dev",
"custom": true,
"id": "04f4e431-4d74-43f1-86d5-52d410f3f6e8",
"type": "pulumi:providers:docker-build",
"inputs": {
"__internal": {},
"host": ""
},
"outputs": {
"host": ""
},
"created": "2025-01-14T20:40:28.862159Z",
"modified": "2025-01-14T20:40:28.862159Z"
},
{
"urn": "urn:pulumi:test::provider-docker-build::docker-build:index:Image::inline",
"custom": true,
"id": "inline",
"type": "docker-build:index:Image",
"inputs": {
"buildOnPreview": true,
"context": {
"location": "."
},
"dockerfile": {
"inline": "FROM alpine\nRUN echo \"This uses an inline Dockerfile! 👍\"\n",
"location": ""
},
"exec": false,
"load": false,
"network": "default",
"noCache": false,
"pull": false,
"push": false,
"target": ""
},
"outputs": {
"buildOnPreview": true,
"context": {
"location": "."
},
"contextHash": "a9db789a55c8ad91fe04e176aefcf0b74f86636ae12e7cd475421416672da8c1",
"digest": "",
"dockerfile": {
"inline": "FROM alpine\nRUN echo \"This uses an inline Dockerfile! 👍\"\n",
"location": ""
},
"exec": false,
"load": false,
"network": "default",
"noCache": false,
"pull": false,
"push": false,
"ref": "",
"target": ""
},
"parent": "urn:pulumi:test::provider-docker-build::pulumi:pulumi:Stack::provider-docker-build-test",
"provider": "urn:pulumi:test::provider-docker-build::pulumi:providers:docker-build::default_0_1_0_alpha_0_dev::04f4e431-4d74-43f1-86d5-52d410f3f6e8",
"propertyDependencies": {
"buildOnPreview": [],
"dockerfile": [],
"network": [],
"push": []
},
"created": "2025-01-14T20:40:32.357012Z",
"modified": "2025-01-14T20:40:32.357012Z",
"sourcePosition": "project:///index.ts#4,16"
}
],
"metadata": {}
}
}

View File

@@ -0,0 +1,6 @@
name: provider-docker-build
runtime: nodejs
plugins:
providers:
- name: docker-build
path: ../../bin

View File

@@ -0,0 +1,11 @@
import * as pulumi from "@pulumi/pulumi";
import * as docker_build from "@pulumi/docker-build";
const inline = new docker_build.Image("inline", {
push: false,
dockerfile: {
inline: `FROM alpine
RUN echo "This uses an inline Dockerfile! 👍"
`,
},
});

View File

@@ -0,0 +1,10 @@
{
"name": "provider-docker-build",
"devDependencies": {
"@types/node": "^18"
},
"dependencies": {
"typescript": "^4.0.0",
"@pulumi/pulumi": "3.144.1"
}
}

View File

@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"files": [
"index.ts",
]
}

View File

@@ -66,7 +66,7 @@ func (c *Config) Configure(ctx context.Context) error {
// NewBuildxProvider returns a new buildx provider.
func NewBuildxProvider() provider.Provider {
return infer.Provider(
prov := infer.Provider(
infer.Options{
Metadata: pschema.Metadata{
DisplayName: "docker-build",
@@ -122,6 +122,27 @@ func NewBuildxProvider() provider.Provider {
Config: infer.Config[*Config](),
},
)
prov.DiffConfig = diffConfigIgnoreInternal(prov.DiffConfig)
return prov
}
// TODO(pulumi/pulumi-docker-build#404): Remove this function once the bug is fixed in either
// upstream pu/pu or pulumi-go-provider.
// diffConfigInternalIgnore is a custom DiffConfig implementation for the buildx provider. This is required to
// circumvent the bug identified in https://github.com/pulumi/pulumi-docker-build/issues/404.
// Since `__internal` is currently populated in new inputs, but stripped in old state, we need to
// ignore this field in the diff. There is no easy way to override DiffConfig to compare inputs only.
func diffConfigIgnoreInternal(
diffConfig func(ctx context.Context, req provider.DiffRequest) (provider.DiffResponse, error),
) func(ctx context.Context, req provider.DiffRequest) (provider.DiffResponse, error) {
return func(ctx context.Context, req provider.DiffRequest) (provider.DiffResponse, error) {
delete(req.News, "__internal")
return diffConfig(ctx, req)
}
}
// Schema returns our package specification.