diff --git a/CHANGELOG.md b/CHANGELOG.md index f1ea3ed..79ee606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/examples/nodejs_test.go b/examples/nodejs_test.go index b0bad04..0a283a5 100644 --- a/examples/nodejs_test.go +++ b/examples/nodejs_test.go @@ -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. diff --git a/examples/testdata/recorded/TestProviderUpgrade/upgrade-node/0.0.7/grpc.json b/examples/testdata/recorded/TestProviderUpgrade/upgrade-node/0.0.7/grpc.json new file mode 100644 index 0000000..98ef671 --- /dev/null +++ b/examples/testdata/recorded/TestProviderUpgrade/upgrade-node/0.0.7/grpc.json @@ -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":{}} \ No newline at end of file diff --git a/examples/testdata/recorded/TestProviderUpgrade/upgrade-node/0.0.7/stack.json b/examples/testdata/recorded/TestProviderUpgrade/upgrade-node/0.0.7/stack.json new file mode 100644 index 0000000..925b174 --- /dev/null +++ b/examples/testdata/recorded/TestProviderUpgrade/upgrade-node/0.0.7/stack.json @@ -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": {} + } +} \ No newline at end of file diff --git a/examples/upgrade-node/Pulumi.yaml b/examples/upgrade-node/Pulumi.yaml new file mode 100644 index 0000000..e5ddad5 --- /dev/null +++ b/examples/upgrade-node/Pulumi.yaml @@ -0,0 +1,6 @@ +name: provider-docker-build +runtime: nodejs +plugins: + providers: + - name: docker-build + path: ../../bin diff --git a/examples/upgrade-node/index.ts b/examples/upgrade-node/index.ts new file mode 100644 index 0000000..593cec8 --- /dev/null +++ b/examples/upgrade-node/index.ts @@ -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! 👍" +`, + }, +}); diff --git a/examples/upgrade-node/package.json b/examples/upgrade-node/package.json new file mode 100644 index 0000000..b3f50e1 --- /dev/null +++ b/examples/upgrade-node/package.json @@ -0,0 +1,10 @@ +{ + "name": "provider-docker-build", + "devDependencies": { + "@types/node": "^18" + }, + "dependencies": { + "typescript": "^4.0.0", + "@pulumi/pulumi": "3.144.1" + } +} diff --git a/examples/upgrade-node/tsconfig.json b/examples/upgrade-node/tsconfig.json new file mode 100644 index 0000000..11fc69a --- /dev/null +++ b/examples/upgrade-node/tsconfig.json @@ -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", + ] +} \ No newline at end of file diff --git a/provider/internal/provider.go b/provider/internal/provider.go index 089fe1f..92c232f 100644 --- a/provider/internal/provider.go +++ b/provider/internal/provider.go @@ -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.