diff --git a/.pulumi.version b/.pulumi.version index 1f201ea..7215c4c 100644 --- a/.pulumi.version +++ b/.pulumi.version @@ -1 +1 @@ -3.163.0 +3.169.0 diff --git a/Makefile b/Makefile index a43c516..4ac189a 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ ${PULUMI}: go.sum GOBIN=${WORKING_DIR}/bin go install github.com/pulumi/pulumi/sdk/nodejs/cmd/pulumi-language-nodejs/v3 GOBIN=${WORKING_DIR}/bin go install github.com/pulumi/pulumi/sdk/python/cmd/pulumi-language-python/v3 GOBIN=${WORKING_DIR}/bin go install github.com/pulumi/pulumi-java/pkg/cmd/pulumi-language-java - GOBIN=${WORKING_DIR}/bin go install github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet + GOBIN=${WORKING_DIR}/bin go install github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet/v3 GOBIN=${WORKING_DIR}/bin go install github.com/pulumi/pulumi-yaml/cmd/pulumi-converter-yaml ${GOGLANGCILINT}: go.sum diff --git a/examples/python/__main__.py b/examples/python/__main__.py index e09d474..7cf848c 100644 --- a/examples/python/__main__.py +++ b/examples/python/__main__.py @@ -5,151 +5,151 @@ config = pulumi.Config() docker_hub_password = config.require("dockerHubPassword") multi_platform = docker_build.Image("multiPlatform", push=False, - dockerfile=docker_build.DockerfileArgs( - location="./app/Dockerfile.multiPlatform", - ), - context=docker_build.BuildContextArgs( - location="./app", - ), + dockerfile={ + "location": "./app/Dockerfile.multiPlatform", + }, + context={ + "location": "./app", + }, platforms=[ docker_build.Platform.PLAN9_AMD64, docker_build.Platform.PLAN9_386, ]) registry_push = docker_build.Image("registryPush", push=False, - context=docker_build.BuildContextArgs( - location="./app", - ), + context={ + "location": "./app", + }, tags=["docker.io/pulumibot/buildkit-e2e:example"], - exports=[docker_build.ExportArgs( - registry=docker_build.ExportRegistryArgs( - oci_media_types=True, - push=False, - ), - )], - registries=[docker_build.RegistryArgs( - address="docker.io", - username="pulumibot", - password=docker_hub_password, - )]) + exports=[{ + "registry": { + "oci_media_types": True, + "push": False, + }, + }], + registries=[{ + "address": "docker.io", + "username": "pulumibot", + "password": docker_hub_password, + }]) cached = docker_build.Image("cached", push=False, - context=docker_build.BuildContextArgs( - location="./app", - ), - cache_to=[docker_build.CacheToArgs( - local=docker_build.CacheToLocalArgs( - dest="tmp/cache", - mode=docker_build.CacheMode.MAX, - ), - )], - cache_from=[docker_build.CacheFromArgs( - local=docker_build.CacheFromLocalArgs( - src="tmp/cache", - ), - )]) + context={ + "location": "./app", + }, + cache_to=[{ + "local": { + "dest": "tmp/cache", + "mode": docker_build.CacheMode.MAX, + }, + }], + cache_from=[{ + "local": { + "src": "tmp/cache", + }, + }]) build_args = docker_build.Image("buildArgs", push=False, - dockerfile=docker_build.DockerfileArgs( - location="./app/Dockerfile.buildArgs", - ), - context=docker_build.BuildContextArgs( - location="./app", - ), + dockerfile={ + "location": "./app/Dockerfile.buildArgs", + }, + context={ + "location": "./app", + }, build_args={ "SET_ME_TO_TRUE": "true", }) extra_hosts = docker_build.Image("extraHosts", push=False, - dockerfile=docker_build.DockerfileArgs( - location="./app/Dockerfile.extraHosts", - ), - context=docker_build.BuildContextArgs( - location="./app", - ), + dockerfile={ + "location": "./app/Dockerfile.extraHosts", + }, + context={ + "location": "./app", + }, add_hosts=["metadata.google.internal:169.254.169.254"]) ssh_mount = docker_build.Image("sshMount", push=False, - dockerfile=docker_build.DockerfileArgs( - location="./app/Dockerfile.sshMount", - ), - context=docker_build.BuildContextArgs( - location="./app", - ), - ssh=[docker_build.SSHArgs( - id="default", - )]) + dockerfile={ + "location": "./app/Dockerfile.sshMount", + }, + context={ + "location": "./app", + }, + ssh=[{ + "id": "default", + }]) secrets = docker_build.Image("secrets", push=False, - dockerfile=docker_build.DockerfileArgs( - location="./app/Dockerfile.secrets", - ), - context=docker_build.BuildContextArgs( - location="./app", - ), + dockerfile={ + "location": "./app/Dockerfile.secrets", + }, + context={ + "location": "./app", + }, secrets={ "password": "hunter2", }) labels = docker_build.Image("labels", push=False, - context=docker_build.BuildContextArgs( - location="./app", - ), + context={ + "location": "./app", + }, labels={ "description": "This image will get a descriptive label 👍", }) target = docker_build.Image("target", push=False, - dockerfile=docker_build.DockerfileArgs( - location="./app/Dockerfile.target", - ), - context=docker_build.BuildContextArgs( - location="./app", - ), + dockerfile={ + "location": "./app/Dockerfile.target", + }, + context={ + "location": "./app", + }, target="build-me") named_contexts = docker_build.Image("namedContexts", push=False, - dockerfile=docker_build.DockerfileArgs( - location="./app/Dockerfile.namedContexts", - ), - context=docker_build.BuildContextArgs( - location="./app", - named={ - "golang:latest": docker_build.ContextArgs( - location="docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984", - ), + dockerfile={ + "location": "./app/Dockerfile.namedContexts", + }, + context={ + "location": "./app", + "named": { + "golang:latest": { + "location": "docker-image://golang@sha256:b8e62cf593cdaff36efd90aa3a37de268e6781a2e68c6610940c48f7cdf36984", + }, }, - )) + }) remote_context = docker_build.Image("remoteContext", push=False, - context=docker_build.BuildContextArgs( - location="https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile", - )) + context={ + "location": "https://raw.githubusercontent.com/pulumi/pulumi-docker/api-types/provider/testdata/Dockerfile", + }) remote_context_with_inline = docker_build.Image("remoteContextWithInline", push=False, - dockerfile=docker_build.DockerfileArgs( - inline="""FROM busybox + dockerfile={ + "inline": """FROM busybox COPY hello.c ./ """, - ), - context=docker_build.BuildContextArgs( - location="https://github.com/docker-library/hello-world.git", - )) + }, + context={ + "location": "https://github.com/docker-library/hello-world.git", + }) inline = docker_build.Image("inline", push=False, - dockerfile=docker_build.DockerfileArgs( - inline="""FROM alpine + dockerfile={ + "inline": """FROM alpine RUN echo "This uses an inline Dockerfile! 👍" """, - )) + }) docker_load = docker_build.Image("dockerLoad", push=False, - context=docker_build.BuildContextArgs( - location="./app", - ), - exports=[docker_build.ExportArgs( - docker=docker_build.ExportDockerArgs( - tar=True, - ), - )]) + context={ + "location": "./app", + }, + exports=[{ + "docker": { + "tar": True, + }, + }]) pulumi.export("platforms", multi_platform.platforms) diff --git a/go.mod b/go.mod index bd64e0b..105bb1d 100644 --- a/go.mod +++ b/go.mod @@ -15,15 +15,15 @@ require ( github.com/muesli/reflow v0.3.0 github.com/otiai10/copy v1.14.0 github.com/pulumi/providertest v0.3.1 - github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet v0.0.0-20241219213128-b19d8c8da35b - github.com/pulumi/pulumi-go-provider v0.26.0 - github.com/pulumi/pulumi-java/pkg v1.10.1-0.20250501074704-87881c4a7c04 + github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet/v3 v3.0.0-20250515194217-855e3e4c894c + github.com/pulumi/pulumi-go-provider v1.0.0-rc.2 + github.com/pulumi/pulumi-java/pkg v1.11.0 github.com/pulumi/pulumi-yaml v1.17.0 - github.com/pulumi/pulumi/pkg/v3 v3.165.0 - github.com/pulumi/pulumi/sdk/go/pulumi-language-go/v3 v3.0.0-20250417110128-49fb14839a5a - github.com/pulumi/pulumi/sdk/nodejs/cmd/pulumi-language-nodejs/v3 v3.0.0-20250417110128-49fb14839a5a - github.com/pulumi/pulumi/sdk/python/cmd/pulumi-language-python/v3 v3.0.0-20250417110128-49fb14839a5a - github.com/pulumi/pulumi/sdk/v3 v3.165.0 + github.com/pulumi/pulumi/pkg/v3 v3.169.0 + github.com/pulumi/pulumi/sdk/go/pulumi-language-go/v3 v3.0.0-20250508095305-a4bdc94d01aa + github.com/pulumi/pulumi/sdk/nodejs/cmd/pulumi-language-nodejs/v3 v3.0.0-20250508095305-a4bdc94d01aa + github.com/pulumi/pulumi/sdk/python/cmd/pulumi-language-python/v3 v3.0.0-20250508095305-a4bdc94d01aa + github.com/pulumi/pulumi/sdk/v3 v3.169.0 github.com/regclient/regclient v0.7.1 github.com/sirupsen/logrus v1.9.3 github.com/spf13/afero v1.14.0 @@ -34,7 +34,7 @@ require ( go.opentelemetry.io/otel/sdk v1.35.0 go.opentelemetry.io/otel/trace v1.35.0 go.uber.org/mock v0.5.2 - golang.org/x/crypto v0.37.0 + golang.org/x/crypto v0.38.0 golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 google.golang.org/protobuf v1.36.6 gopkg.in/yaml.v3 v3.0.1 @@ -459,12 +459,12 @@ require ( gocloud.dev/secrets/hashivault v0.37.0 // indirect golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f // indirect golang.org/x/mod v0.24.0 // indirect - golang.org/x/net v0.39.0 // indirect + golang.org/x/net v0.40.0 // indirect golang.org/x/oauth2 v0.25.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/term v0.31.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/time v0.6.0 // indirect golang.org/x/tools v0.32.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect diff --git a/go.sum b/go.sum index f5fb5e7..5215e3e 100644 --- a/go.sum +++ b/go.sum @@ -886,24 +886,24 @@ github.com/pulumi/inflector v0.2.1 h1:bqyiish3tq//vLeLiEstSFE5K7RNjy/ce47ed4QATu github.com/pulumi/inflector v0.2.1/go.mod h1:HUFCjcPTz96YtTuUlwG3i3EZG4WlniBvR9bd+iJxCUY= github.com/pulumi/providertest v0.3.1 h1:vlftr7TZlObh81mL88IhhF0/9ZbLrZZos4NAvR4HUUw= github.com/pulumi/providertest v0.3.1/go.mod h1:fFHUP4/9DRyYnHWiRnwcynMtM/a7hHR/QcJfcuZKO3A= -github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet v0.0.0-20241219213128-b19d8c8da35b h1:pyYHkDsogl5q4dorkTKVk4/87l+fFUEIIVuwBqKJMHM= -github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet v0.0.0-20241219213128-b19d8c8da35b/go.mod h1:5LjEUmPDpUyXzFbQCy3s1oFgeU9K3gVA6tX+xn1Xvbo= -github.com/pulumi/pulumi-go-provider v0.26.0 h1:3ia10+irvv7qPph2NZ2YwUGI/KCf6li8Frlc1luv7D4= -github.com/pulumi/pulumi-go-provider v0.26.0/go.mod h1:zJiGxY5xnodPzLulpRS+fsS960MzeCdlsdiVCZ5TMRA= -github.com/pulumi/pulumi-java/pkg v1.10.1-0.20250501074704-87881c4a7c04 h1:JtnozyKVJrV3ITXhnZL82lO3V8pbqrA+p5co8b3hbr4= -github.com/pulumi/pulumi-java/pkg v1.10.1-0.20250501074704-87881c4a7c04/go.mod h1:fE/A/3U2rpqpQKG0RrmmHjf0q+7shjsSfi74mhmLF6g= +github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet/v3 v3.0.0-20250515194217-855e3e4c894c h1:UTPnj4E06/n+T6ffEevqvS2f+zKLdRBeM81aQwhwNlE= +github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet/v3 v3.0.0-20250515194217-855e3e4c894c/go.mod h1:4XmrdCzJ36AigIW8B0HWjkjfgmY2DZTLqv4BQal3hSg= +github.com/pulumi/pulumi-go-provider v1.0.0-rc.2 h1:Fkv+MVGOE4XBwZ7M3Tp4vVWu3YE6w1pCod0vmMkukm0= +github.com/pulumi/pulumi-go-provider v1.0.0-rc.2/go.mod h1:84yaWdhVcyPG+Vq3HfcDPPeGsNEMIQCD+S1WsymEw9A= +github.com/pulumi/pulumi-java/pkg v1.11.0 h1:M8C7CKxwBSE/c5RcoGF0sAUSFZywjd7CjmTRQh8nvNk= +github.com/pulumi/pulumi-java/pkg v1.11.0/go.mod h1:zoQdTjj488DhUx8dNed6SW1fJnAE4GwGLBVDRpsQVE8= github.com/pulumi/pulumi-yaml v1.17.0 h1:ebzggygqBcQrtmdBUqi28B1L/fAyHCFVIt0dS5re8Oc= github.com/pulumi/pulumi-yaml v1.17.0/go.mod h1:4cpS4ITkIAXgVedTZB3JY/DnZu9XSh+RhrKB5WlB/fs= -github.com/pulumi/pulumi/pkg/v3 v3.165.0 h1:a0UOxhM+yUi5NH+SP5lv0YHxac3JOaeaZ/VINVkK+bM= -github.com/pulumi/pulumi/pkg/v3 v3.165.0/go.mod h1:wJDlCqph9G1OCX8BYfjRp8yOtqBXZLij57fGbn1lXsM= -github.com/pulumi/pulumi/sdk/go/pulumi-language-go/v3 v3.0.0-20250417110128-49fb14839a5a h1:4V6DbJaLLSvOc9J/7ODqQEg892LaPD2JZtB9pKpHPI0= -github.com/pulumi/pulumi/sdk/go/pulumi-language-go/v3 v3.0.0-20250417110128-49fb14839a5a/go.mod h1:kle5wfWZA+tNa8M/8tBVk6yLE2kGqYtD3VEIpl8Vc6Y= -github.com/pulumi/pulumi/sdk/nodejs/cmd/pulumi-language-nodejs/v3 v3.0.0-20250417110128-49fb14839a5a h1:5QPCsb+EAqwB2N70hXHPJig8eKi02Gttm9pGs9PQf2I= -github.com/pulumi/pulumi/sdk/nodejs/cmd/pulumi-language-nodejs/v3 v3.0.0-20250417110128-49fb14839a5a/go.mod h1:9z23xCno15uQcyMDfFgXpISVExs/yXDuPsi5L8ykeRU= -github.com/pulumi/pulumi/sdk/python/cmd/pulumi-language-python/v3 v3.0.0-20250417110128-49fb14839a5a h1:4JkTGfh7AMYWlngOHk1V5m3US5JQsphUsQBpfCCW5yg= -github.com/pulumi/pulumi/sdk/python/cmd/pulumi-language-python/v3 v3.0.0-20250417110128-49fb14839a5a/go.mod h1:IhJFvQ3XHlTfik9Gmlw5A7KMGXOK+UMQuslTS0cuojA= -github.com/pulumi/pulumi/sdk/v3 v3.165.0 h1:cglplKZOJDpqH8wa/2J250G9az/sE9eKp9fS2bC+vi8= -github.com/pulumi/pulumi/sdk/v3 v3.165.0/go.mod h1:GAaHrdv3kWJHbzkFFFflGbTBQXUYu6SF1ZCo+O9jo44= +github.com/pulumi/pulumi/pkg/v3 v3.169.0 h1:q1f36HRYhXEKZVe3b0SQGKJjl+9llCHzAztn+aiidtE= +github.com/pulumi/pulumi/pkg/v3 v3.169.0/go.mod h1:ofgvwLttErApwvvvvmx40VhxEoNl34q0XVSraK40RqQ= +github.com/pulumi/pulumi/sdk/go/pulumi-language-go/v3 v3.0.0-20250508095305-a4bdc94d01aa h1:b0CMni/Q621ChYaTe6FMHXYfrcH1FzAXjUsOsUO24nc= +github.com/pulumi/pulumi/sdk/go/pulumi-language-go/v3 v3.0.0-20250508095305-a4bdc94d01aa/go.mod h1:5Vs9hUjv9+R4K97UUul5KjFIpUi0AmZdVZVE+Yl0UoY= +github.com/pulumi/pulumi/sdk/nodejs/cmd/pulumi-language-nodejs/v3 v3.0.0-20250508095305-a4bdc94d01aa h1:RB9e9Gc4PMyX+IRdfR7VipRQeBdc3K93ROrnbmHS6V0= +github.com/pulumi/pulumi/sdk/nodejs/cmd/pulumi-language-nodejs/v3 v3.0.0-20250508095305-a4bdc94d01aa/go.mod h1:5lah9DjodVv9BURtk2ykbJams7TclP+Xr7h+NK4B0gQ= +github.com/pulumi/pulumi/sdk/python/cmd/pulumi-language-python/v3 v3.0.0-20250508095305-a4bdc94d01aa h1:3eGefORCsSeUrIYe9GIklycGRoKsKAGq3dfg1RYb3nM= +github.com/pulumi/pulumi/sdk/python/cmd/pulumi-language-python/v3 v3.0.0-20250508095305-a4bdc94d01aa/go.mod h1:6LYkwLXNHz68cnVIgdsthaUaxZZDIJp1Ag0RyUnPNek= +github.com/pulumi/pulumi/sdk/v3 v3.169.0 h1:bgz1fp2rl28khSXgF4FaRQiB9wh3lSKWtzUOGalf+x4= +github.com/pulumi/pulumi/sdk/v3 v3.169.0/go.mod h1:Qhe4dOjqedyLr47kGGnG6ULIbzaPTlmjAvPqNQ1Ollo= github.com/quasilyte/go-ruleguard v0.4.2 h1:htXcXDK6/rO12kiTHKfHuqR4kr3Y4M0J0rOL6CH/BYs= github.com/quasilyte/go-ruleguard v0.4.2/go.mod h1:GJLgqsLeo4qgavUoL8JeGFNS7qcisx3awV/w9eWTmNI= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= @@ -1196,8 +1196,8 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= @@ -1250,8 +1250,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -1267,8 +1267,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1311,8 +1311,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1323,8 +1323,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -1336,8 +1336,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/provider/internal/client.go b/provider/internal/client.go index 2a226d4..f5e7a8b 100644 --- a/provider/internal/client.go +++ b/provider/internal/client.go @@ -63,6 +63,36 @@ type Client interface { SupportsMultipleExports() bool } +// registryGetter is something that can return a list of [Registry]. +type registryGetter interface { + GetRegistries() []Registry +} + +// clientF builds a Docker client. The order of registryGetters is significant. +// We typically prefer credentials from args, then provider config, then the +// host. Provide them to this function in order of increasing priority: host, +// config, args. +// +// We ignore state because if its creds differ from those in args then they are +// likely volatile and also likely expired. +type clientF func(context.Context, *host, ...registryGetter) (Client, error) + +// RealClientF builds a real Docker client with auth layered on top of the +// host's latent credentials. +func RealClientF(_ context.Context, host *host, getters ...registryGetter) (Client, error) { + auths := []Registry{} + for _, rg := range getters { + auths = append(auths, rg.GetRegistries()...) + } + return wrap(host, auths...) +} + +func mockClientF(c Client) clientF { + return func(context.Context, *host, ...registryGetter) (Client, error) { + return c, nil + } +} + // Build encapsulates all of the user-provider build parameters and options. type Build interface { BuildOptions() controllerapi.BuildOptions diff --git a/provider/internal/image.go b/provider/internal/image.go index 04e532e..982abd2 100644 --- a/provider/internal/image.go +++ b/provider/internal/image.go @@ -38,7 +38,7 @@ import ( provider "github.com/pulumi/pulumi-go-provider" "github.com/pulumi/pulumi-go-provider/infer" - "github.com/pulumi/pulumi/sdk/v3/go/common/resource" + "github.com/pulumi/pulumi/sdk/v3/go/property" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -61,7 +61,10 @@ var _imageExamples string var _migration string // Image is a Docker image build using buildkit. -type Image struct{} +type Image struct { + clientF clientF + config *Config +} // Annotate provides a description of the Image resource. func (i *Image) Annotate(a infer.Annotator) { @@ -281,6 +284,11 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) { a.SetDefault(&ia.Network, Default) } +// GetRegistries returns the image's registries, if any. +func (ia ImageArgs) GetRegistries() []Registry { + return ia.Registries +} + // ImageState is serialized to the program's state file. type ImageState struct { ImageArgs @@ -329,38 +337,25 @@ func (is *ImageState) Annotate(a infer.Annotator) { // client produces a CLI client scoped to this resource and layered on top of // any host-level credentials. -func (i *Image) client(ctx context.Context, state ImageState, args ImageArgs) (Client, error) { - cfg := infer.GetConfig[Config](ctx) - - if cli, ok := ctx.Value(_mockClientKey).(Client); ok { - return cli, nil - } - - // We prefer auth from args, the provider, and state in that order. We - // build a slice in reverse order because wrap() will overwrite earlier - // entries with later ones. - auths := []Registry{} - auths = append(auths, cfg.Registries...) - auths = append(auths, args.Registries...) - - return wrap(cfg.host, auths...) +func (i *Image) client(ctx context.Context, args ImageArgs) (Client, error) { + return i.clientF(ctx, i.config.getHost(), i.config, args) } // Check validates ImageArgs, sets defaults, and ensures our client is // authenticated. func (i *Image) Check( ctx context.Context, - _ string, - _ resource.PropertyMap, - news resource.PropertyMap, -) (ImageArgs, []provider.CheckFailure, error) { - args, failures, err := infer.DefaultCheck[ImageArgs](ctx, news) + req infer.CheckRequest, +) (infer.CheckResponse[ImageArgs], error) { + args, failures, err := infer.DefaultCheck[ImageArgs](ctx, req.NewInputs) if err != nil || len(failures) != 0 { - return args, failures, err + return infer.CheckResponse[ImageArgs]{Failures: failures, Inputs: args}, err } - // :( - preview := news.ContainsUnknowns() + // If the inputs aren't fully resolved we perform a weaker validation, for + // example we might not be able to check the Dockerfile for syntactic + // correctness. + preview := property.New(req.NewInputs).HasComputed() cfg := infer.GetConfig[Config](ctx) supportsMultipleExports := true @@ -376,7 +371,7 @@ func (i *Image) Check( } } - return args, failures, err + return infer.CheckResponse[ImageArgs]{Failures: failures, Inputs: args}, err } type checkFailure struct { @@ -683,12 +678,11 @@ func (ia *ImageArgs) validate(supportsMultipleExports, preview bool) (controller // Create builds an image using buildkit. func (i *Image) Create( ctx context.Context, - name string, - input ImageArgs, - preview bool, -) (string, ImageState, error) { + req infer.CreateRequest[ImageArgs], +) (infer.CreateResponse[ImageState], error) { + input := req.Inputs state := ImageState{ImageArgs: input} - id := name + id := req.Name // Default our ref to one of our tags. for _, tag := range state.Tags { @@ -699,22 +693,31 @@ func (i *Image) Create( break } - cli, err := i.client(ctx, state, input) + cli, err := i.client(ctx, input) if err != nil { - return id, state, err + return infer.CreateResponse[ImageState]{ID: id, Output: state}, err } ok, err := cli.BuildKitEnabled() if err != nil { - return id, state, fmt.Errorf("checking buildkit compatibility: %w", err) + return infer.CreateResponse[ImageState]{ + ID: id, + Output: state, + }, fmt.Errorf("checking buildkit compatibility: %w", err) } if !ok { - return id, state, errors.New("buildkit is not supported on this host") + return infer.CreateResponse[ImageState]{ + ID: id, + Output: state, + }, errors.New("buildkit is not supported on this host") } - build, err := input.toBuild(ctx, cli.SupportsMultipleExports(), preview) + build, err := input.toBuild(ctx, cli.SupportsMultipleExports(), req.DryRun) if err != nil { - return id, state, fmt.Errorf("preparing: %w", err) + return infer.CreateResponse[ImageState]{ + ID: id, + Output: state, + }, fmt.Errorf("preparing: %w", err) } hash, err := hashBuildContext( @@ -723,21 +726,24 @@ func (i *Image) Create( input.Context.Named.Map(), ) if err != nil { - return id, state, fmt.Errorf("hashing build context: %w", err) + return infer.CreateResponse[ImageState]{ + ID: id, + Output: state, + }, fmt.Errorf("hashing build context: %w", err) } state.ContextHash = hash - if preview && !input.shouldBuildOnPreview() { - return id, state, nil + if req.DryRun && !input.shouldBuildOnPreview() { + return infer.CreateResponse[ImageState]{ID: id, Output: state}, nil } - if preview && !input.buildable() { + if req.DryRun && !input.buildable() { provider.GetLogger(ctx).Warning("Skipping preview build because some inputs are unknown.") - return id, state, nil + return infer.CreateResponse[ImageState]{ID: id, Output: state}, nil } result, err := cli.Build(ctx, build) if err != nil { - return id, state, err + return infer.CreateResponse[ImageState]{ID: id, Output: state}, err } if d, ok := result.ExporterResponse[exptypes.ExporterImageDigestKey]; ok { @@ -747,7 +753,7 @@ func (i *Image) Create( if state.Digest == "" { // Can't construct a ref, nothing else to do. - return id, state, nil + return infer.CreateResponse[ImageState]{ID: id, Output: state}, nil } // Take the first registry tag we find and add a digest to it. That becomes @@ -762,7 +768,7 @@ func (i *Image) Create( break } - return id, state, nil + return infer.CreateResponse[ImageState]{ID: id, Output: state}, nil } // Update builds a new image. Normally we create-replace resources, but for @@ -770,36 +776,41 @@ func (i *Image) Create( // updates and simply re-build the image without deleting anything. func (i *Image) Update( ctx context.Context, - name string, - _ ImageState, - input ImageArgs, - preview bool, -) (ImageState, error) { - _, state, err := i.Create(ctx, name, input, preview) - return state, err + req infer.UpdateRequest[ImageArgs, ImageState], +) (infer.UpdateResponse[ImageState], error) { + resp, err := i.Create(ctx, + infer.CreateRequest[ImageArgs]{Name: req.ID, Inputs: req.Inputs, DryRun: req.DryRun}, + ) + return infer.UpdateResponse[ImageState]{Output: resp.Output}, err } // Read attempts to read manifests from an image's exports. An image without // exports will have no manifests. func (i *Image) Read( ctx context.Context, - name string, - input ImageArgs, - state ImageState, + req infer.ReadRequest[ImageArgs, ImageState], ) ( - string, // id - ImageArgs, // normalized inputs - ImageState, // normalized state + infer.ReadResponse[ImageArgs, ImageState], error, ) { - cli, err := i.client(ctx, state, input) + state, input := req.State, req.Inputs + + cli, err := i.client(ctx, input) if err != nil { - return name, input, state, err + return infer.ReadResponse[ImageArgs, ImageState]{ + ID: req.ID, + Inputs: input, + State: state, + }, err } if !state.isExported() { // Nothing was pushed -- all done. - return name, input, state, nil + return infer.ReadResponse[ImageArgs, ImageState]{ + ID: req.ID, + Inputs: input, + State: state, + }, nil } tagsToKeep := []string{} @@ -835,29 +846,29 @@ func (i *Image) Read( // If we couldn't find the tags we expected then return an empty ID to // delete the resource. if len(input.Tags) > 0 && len(tagsToKeep) == 0 { - return "", input, state, nil + return infer.ReadResponse[ImageArgs, ImageState]{ID: "", Inputs: input, State: state}, nil } state.Tags = tagsToKeep - return name, input, state, nil + return infer.ReadResponse[ImageArgs, ImageState]{ID: req.ID, Inputs: input, State: state}, nil } // Delete deletes an Image. If the Image was already deleted out-of-band it is // treated as a success. func (i *Image) Delete( ctx context.Context, - _ string, - state ImageState, -) error { - cli, err := i.client(ctx, state, state.ImageArgs) + req infer.DeleteRequest[ImageState], +) (infer.DeleteResponse, error) { + state := req.State + cli, err := i.client(ctx, state.ImageArgs) if err != nil { - return err + return infer.DeleteResponse{}, err } if state.Digest == "" { // Nothing was exported. Just try to delete the local image. - return cli.Delete(ctx, state.Ref) + return infer.DeleteResponse{}, cli.Delete(ctx, state.Ref) } digests := []string{} @@ -885,17 +896,17 @@ func (i *Image) Delete( multierr = errors.Join(multierr, err) } - return multierr + return infer.DeleteResponse{}, multierr } // Diff re-implements most of the default diff behavior, with the exception of // ignoring "password" changes on registry inputs. func (*Image) Diff( _ context.Context, - _ string, - olds ImageState, - news ImageArgs, + req infer.DiffRequest[ImageArgs, ImageState], ) (provider.DiffResponse, error) { + olds, news := req.State, req.Inputs + diff := map[string]provider.PropertyDiff{} update := provider.PropertyDiff{Kind: provider.Update} diff --git a/provider/internal/image_test.go b/provider/internal/image_test.go index 6bba7de..defe144 100644 --- a/provider/internal/image_test.go +++ b/provider/internal/image_test.go @@ -35,9 +35,11 @@ import ( "go.uber.org/mock/gomock" provider "github.com/pulumi/pulumi-go-provider" + "github.com/pulumi/pulumi-go-provider/infer" "github.com/pulumi/pulumi-go-provider/integration" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" "github.com/pulumi/pulumi/sdk/v3/go/common/util/mapper" + "github.com/pulumi/pulumi/sdk/v3/go/property" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -84,46 +86,44 @@ func TestImageLifecycle(t *testing.T) { }, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "push": resource.NewBoolProperty(false), - "tags": resource.NewArrayProperty( - []resource.PropertyValue{ - resource.NewStringProperty("docker.io/pulumibot/buildkit-e2e"), - resource.NewStringProperty("docker.io/pulumibot/buildkit-e2e:main"), + Inputs: property.NewMap(map[string]property.Value{ + "push": property.New(false), + "tags": property.New( + []property.Value{ + property.New("docker.io/pulumibot/buildkit-e2e"), + property.New("docker.io/pulumibot/buildkit-e2e:main"), }, ), - "platforms": resource.NewArrayProperty( - []resource.PropertyValue{ - resource.NewStringProperty("linux/arm64"), - resource.NewStringProperty("linux/amd64"), + "platforms": property.New( + []property.Value{ + property.New("linux/arm64"), + property.New("linux/amd64"), }, ), - "context": resource.NewObjectProperty(resource.PropertyMap{ - "location": resource.NewStringProperty("testdata/noop"), + "context": property.New(map[string]property.Value{ + "location": property.New("testdata/noop"), }), - "dockerfile": resource.NewObjectProperty(resource.PropertyMap{ - "location": resource.NewStringProperty("testdata/noop/Dockerfile"), + "dockerfile": property.New(map[string]property.Value{ + "location": property.New("testdata/noop/Dockerfile"), }), - "exports": resource.NewArrayProperty( - []resource.PropertyValue{ - resource.NewObjectProperty(resource.PropertyMap{ - "raw": resource.NewStringProperty("type=registry"), + "exports": property.New( + []property.Value{ + property.New(map[string]property.Value{ + "raw": property.New("type=registry"), }, ), }, ), - "registries": resource.NewArrayProperty( - []resource.PropertyValue{ - resource.NewObjectProperty(resource.PropertyMap{ - "address": resource.NewStringProperty("fakeaddress"), - "username": resource.NewStringProperty("fakeuser"), - "password": resource.MakeSecret( - resource.NewStringProperty("password"), - ), + "registries": property.New( + []property.Value{ + property.New(map[string]property.Value{ + "address": property.New("fakeaddress"), + "username": property.New("fakeuser"), + "password": property.New("password").WithSecret(true), }), }, ), - }, + }), } }, }, @@ -132,20 +132,20 @@ func TestImageLifecycle(t *testing.T) { client: noClient, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "push": resource.NewBoolProperty(false), - "tags": resource.NewArrayProperty([]resource.PropertyValue{}), - "context": resource.NewObjectProperty(resource.PropertyMap{ - "location": resource.NewStringProperty("testdata/noop"), + Inputs: property.NewMap(map[string]property.Value{ + "push": property.New(false), + "tags": property.New([]property.Value{}), + "context": property.New(map[string]property.Value{ + "location": property.New("testdata/noop"), }), - "exports": resource.NewArrayProperty( - []resource.PropertyValue{ - resource.NewObjectProperty(resource.PropertyMap{ - "raw": resource.NewStringProperty("type=registry"), + "exports": property.New( + []property.Value{ + property.New(map[string]property.Value{ + "raw": property.New("type=registry"), }), }, ), - }, + }), ExpectFailure: true, CheckFailures: []provider.CheckFailure{ { @@ -161,19 +161,19 @@ func TestImageLifecycle(t *testing.T) { client: noClient, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "push": resource.NewBoolProperty(false), - "tags": resource.NewArrayProperty( - []resource.PropertyValue{resource.NewStringProperty("invalid-exports")}, + Inputs: property.NewMap(map[string]property.Value{ + "push": property.New(false), + "tags": property.New( + []property.Value{property.New("invalid-exports")}, ), - "exports": resource.NewArrayProperty( - []resource.PropertyValue{ - resource.NewObjectProperty(resource.PropertyMap{ - "raw": resource.NewStringProperty("type="), + "exports": property.New( + []property.Value{ + property.New(map[string]property.Value{ + "raw": property.New("type="), }), }, ), - }, + }), ExpectFailure: true, CheckFailures: []provider.CheckFailure{{ Property: "exports[0]", @@ -194,15 +194,15 @@ func TestImageLifecycle(t *testing.T) { }, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "push": resource.NewBoolProperty(false), - "tags": resource.NewArrayProperty( - []resource.PropertyValue{resource.NewStringProperty("foo")}, + Inputs: property.NewMap(map[string]property.Value{ + "push": property.New(false), + "tags": property.New( + []property.Value{property.New("foo")}, ), - "context": resource.NewObjectProperty(resource.PropertyMap{ - "location": resource.NewStringProperty("testdata/noop"), + "context": property.New(map[string]property.Value{ + "location": property.New("testdata/noop"), }), - }, + }), ExpectFailure: true, } }, @@ -221,15 +221,15 @@ func TestImageLifecycle(t *testing.T) { }, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "push": resource.NewBoolProperty(false), - "tags": resource.NewArrayProperty( - []resource.PropertyValue{resource.NewStringProperty("foo")}, + Inputs: property.NewMap(map[string]property.Value{ + "push": property.New(false), + "tags": property.New( + []property.Value{property.New("foo")}, ), - "context": resource.NewObjectProperty(resource.PropertyMap{ - "location": resource.NewStringProperty("testdata/noop"), + "context": property.New(map[string]property.Value{ + "location": property.New("testdata/noop"), }), - }, + }), ExpectFailure: true, } }, @@ -254,24 +254,24 @@ func TestImageLifecycle(t *testing.T) { }, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "push": resource.NewBoolProperty(false), - "tags": resource.NewArrayProperty( - []resource.PropertyValue{ - resource.NewStringProperty("default-dockerfile"), + Inputs: property.NewMap(map[string]property.Value{ + "push": property.New(false), + "tags": property.New( + []property.Value{ + property.New("default-dockerfile"), }, ), - "context": resource.NewObjectProperty(resource.PropertyMap{ - "location": resource.NewStringProperty("testdata/noop"), + "context": property.New(map[string]property.Value{ + "location": property.New("testdata/noop"), }), - }, - Hook: func(_, output resource.PropertyMap) { - dockerfile := output["dockerfile"] + }), + Hook: func(_, output property.Map) { + dockerfile := output.Get("dockerfile") require.NotNil(t, dockerfile) - require.True(t, dockerfile.IsObject()) - location := dockerfile.ObjectValue()["location"] + require.True(t, dockerfile.IsMap()) + location := dockerfile.AsMap().Get("location") require.True(t, location.IsString()) - assert.Equal(t, "testdata/noop/Dockerfile", location.StringValue()) + assert.Equal(t, "testdata/noop/Dockerfile", location.AsString()) }, } }, @@ -296,25 +296,25 @@ func TestImageLifecycle(t *testing.T) { }, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "push": resource.NewBoolProperty(false), - "tags": resource.NewArrayProperty( - []resource.PropertyValue{ - resource.NewStringProperty("inline-dockerfile"), + Inputs: property.NewMap(map[string]property.Value{ + "push": property.New(false), + "tags": property.New( + []property.Value{ + property.New("inline-dockerfile"), }, ), - "buildOnPreview": resource.NewBoolProperty(true), - "dockerfile": resource.NewObjectProperty(resource.PropertyMap{ - "inline": resource.NewStringProperty("FROM alpine:latest"), + "buildOnPreview": property.New(true), + "dockerfile": property.New(map[string]property.Value{ + "inline": property.New("FROM alpine:latest"), }), - }, - Hook: func(_, output resource.PropertyMap) { - context := output["context"] + }), + Hook: func(_, output property.Map) { + context := output.Get("context") require.NotNil(t, context) - require.True(t, context.IsObject()) - location := context.ObjectValue()["location"] + require.True(t, context.IsMap()) + location := context.AsMap().Get("location") require.True(t, location.IsString()) - assert.Equal(t, ".", location.StringValue()) + assert.Equal(t, ".", location.AsString()) }, } }, @@ -328,7 +328,7 @@ func TestImageLifecycle(t *testing.T) { Resource: "docker-build:index:Image", Create: tt.op(t), } - s := newServer(tt.client(t)) + s := newServer(t.Context(), t, mockClientF(tt.client(t))) err := s.Configure(provider.ConfigureRequest{}) require.NoError(t, err) @@ -353,21 +353,16 @@ func TestDelete(t *testing.T) { Delete(gomock.Any(), "docker.io/pulumi/test@sha256:foo"). Return(errNotFound{}) - s := newServer(client) - err := s.Configure(provider.ConfigureRequest{}) - require.NoError(t, err) + i := &Image{clientF: mockClientF(client)} - err = s.Delete(provider.DeleteRequest{ - ID: "foo,bar", - Urn: _fakeURN, - Properties: resource.PropertyMap{ - "tags": resource.NewArrayProperty([]resource.PropertyValue{ - resource.NewStringProperty("docker.io/pulumi/test:foo"), - }), - "push": resource.NewBoolProperty(true), - "digest": resource.NewStringProperty("sha256:foo"), - "contextHash": resource.NewStringProperty(""), - "ref": resource.NewStringProperty(""), + _, err := i.Delete(t.Context(), infer.DeleteRequest[ImageState]{ + ID: "foo,bar", + State: ImageState{ + ImageArgs: ImageArgs{ + Tags: []string{"docker.io/pulumi/test:foo"}, + Push: true, + }, + Digest: "sha256:foo", }, }) assert.NoError(t, err) @@ -391,27 +386,21 @@ func TestRead(t *testing.T) { }, }, nil) - s := newServer(client) - err := s.Configure(provider.ConfigureRequest{}) - require.NoError(t, err) + i := &Image{clientF: mockClientF(client)} - resp, err := s.Read(provider.ReadRequest{ - ID: "my-image", - Urn: _fakeURN, - Properties: resource.PropertyMap{ - "exports": resource.NewArrayProperty([]resource.PropertyValue{ - resource.NewObjectProperty(resource.PropertyMap{ - "raw": resource.NewStringProperty("type=registry"), - }), - }), - "tags": resource.NewArrayProperty([]resource.PropertyValue{ - resource.NewStringProperty(tag), - }), - "digest": resource.NewStringProperty(digest), + resp, err := i.Read(t.Context(), infer.ReadRequest[ImageArgs, ImageState]{ + ID: "my-image", + State: ImageState{ + ImageArgs: ImageArgs{ + Exports: []Export{{Raw: "type=registry"}}, + Tags: []string{tag}, + }, + Digest: digest, }, }) + require.NoError(t, err) - assert.NotNil(t, resp.Properties["exports"].ArrayValue()[0].ObjectValue()["manifest"]) + assert.Equal(t, []string{tag}, resp.State.Tags) } func TestImageDiff(t *testing.T) { @@ -432,21 +421,21 @@ func TestImageDiff(t *testing.T) { } tests := []struct { - name string - olds func(*testing.T, ImageState) ImageState - news func(*testing.T, ImageArgs) ImageArgs + name string + state func(*testing.T, ImageState) ImageState + inputs func(*testing.T, ImageArgs) ImageArgs wantChanges bool }{ { name: "no diff if build context is unchanged", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(*testing.T, ImageArgs) ImageArgs { return baseArgs }, + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(*testing.T, ImageArgs) ImageArgs { return baseArgs }, wantChanges: false, }, { name: "no diff if registry password changes", - olds: func(_ *testing.T, s ImageState) ImageState { + state: func(_ *testing.T, s ImageState) ImageState { s.Registries = []Registry{{ Address: "foo", Username: "foo", @@ -454,7 +443,7 @@ func TestImageDiff(t *testing.T) { }} return s }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Registries = []Registry{{ Address: "foo", Username: "foo", @@ -466,11 +455,11 @@ func TestImageDiff(t *testing.T) { }, { name: "no diff if pull=true but no exports", - olds: func(_ *testing.T, is ImageState) ImageState { + state: func(_ *testing.T, is ImageState) ImageState { is.Pull = true return is }, - news: func(t *testing.T, ia ImageArgs) ImageArgs { + inputs: func(t *testing.T, ia ImageArgs) ImageArgs { ia.Pull = true return ia }, @@ -478,12 +467,12 @@ func TestImageDiff(t *testing.T) { }, { name: "diff if pull=true with exports", - olds: func(_ *testing.T, is ImageState) ImageState { + state: func(_ *testing.T, is ImageState) ImageState { is.Pull = true is.Load = true return is }, - news: func(t *testing.T, ia ImageArgs) ImageArgs { + inputs: func(t *testing.T, ia ImageArgs) ImageArgs { ia.Pull = true ia.Load = true return ia @@ -491,9 +480,9 @@ func TestImageDiff(t *testing.T) { wantChanges: true, }, { - name: "diff if build context changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(t *testing.T, a ImageArgs) ImageArgs { + name: "diff if build context changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(t *testing.T, a ImageArgs) ImageArgs { tmp := filepath.Join(a.Context.Location, "tmp") err := os.WriteFile(tmp, []byte{}, 0o600) require.NoError(t, err) @@ -503,9 +492,9 @@ func TestImageDiff(t *testing.T) { wantChanges: true, }, { - name: "diff if registry added", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if registry added", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Registries = []Registry{{}} return a }, @@ -513,7 +502,7 @@ func TestImageDiff(t *testing.T) { }, { name: "diff if registry user changes", - olds: func(_ *testing.T, s ImageState) ImageState { + state: func(_ *testing.T, s ImageState) ImageState { s.Registries = []Registry{{ Address: "foo", Username: "foo", @@ -521,7 +510,7 @@ func TestImageDiff(t *testing.T) { }} return s }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Registries = []Registry{{ Address: "DIFFERENT USER", Username: "foo", @@ -532,9 +521,9 @@ func TestImageDiff(t *testing.T) { wantChanges: true, }, { - name: "diff if buildArgs changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if buildArgs changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.BuildArgs = map[string]string{ "foo": "bar", } @@ -543,36 +532,36 @@ func TestImageDiff(t *testing.T) { wantChanges: true, }, { - name: "diff if pull changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(t *testing.T, ia ImageArgs) ImageArgs { + name: "diff if pull changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(t *testing.T, ia ImageArgs) ImageArgs { ia.Pull = true return ia }, wantChanges: true, }, { - name: "diff if load changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(t *testing.T, ia ImageArgs) ImageArgs { + name: "diff if load changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(t *testing.T, ia ImageArgs) ImageArgs { ia.Load = true return ia }, wantChanges: true, }, { - name: "diff if push changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(t *testing.T, ia ImageArgs) ImageArgs { + name: "diff if push changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(t *testing.T, ia ImageArgs) ImageArgs { ia.Push = true return ia }, wantChanges: true, }, { - name: "diff if buildOnPreview doesn't change", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(t *testing.T, ia ImageArgs) ImageArgs { + name: "diff if buildOnPreview doesn't change", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(t *testing.T, ia ImageArgs) ImageArgs { val := true ia.BuildOnPreview = &val return ia @@ -580,9 +569,9 @@ func TestImageDiff(t *testing.T) { wantChanges: true, }, { - name: "diff if buildOnPreview changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(t *testing.T, ia ImageArgs) ImageArgs { + name: "diff if buildOnPreview changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(t *testing.T, ia ImageArgs) ImageArgs { val := false ia.BuildOnPreview = &val return ia @@ -590,171 +579,171 @@ func TestImageDiff(t *testing.T) { wantChanges: true, }, { - name: "diff if ssh changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(t *testing.T, ia ImageArgs) ImageArgs { + name: "diff if ssh changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(t *testing.T, ia ImageArgs) ImageArgs { ia.SSH = []SSH{{ID: "default"}} return ia }, wantChanges: true, }, { - name: "diff if hosts change", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(t *testing.T, ia ImageArgs) ImageArgs { + name: "diff if hosts change", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(t *testing.T, ia ImageArgs) ImageArgs { ia.AddHosts = []string{"localhost"} return ia }, wantChanges: true, }, { - name: "diff if cacheFrom changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if cacheFrom changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.CacheFrom = []CacheFrom{{Raw: "a"}} return a }, wantChanges: true, }, { - name: "diff if cacheTo changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if cacheTo changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.CacheTo = []CacheTo{{Raw: "a"}} return a }, wantChanges: true, }, { - name: "diff if context changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if context changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Context = &BuildContext{Context: Context{Location: "testdata/ignores"}} return a }, wantChanges: true, }, { - name: "diff if named context changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if named context changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Context = &BuildContext{Named: NamedContexts{"foo": Context{Location: "bar"}}} return a }, wantChanges: true, }, { - name: "diff if network changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if network changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Network = &host return a }, wantChanges: true, }, { - name: "diff if dockerfile location changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if dockerfile location changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Dockerfile = &Dockerfile{Location: "testdata/ignores/basedir/Dockerfile"} return a }, wantChanges: true, }, { - name: "diff if dockerfile inline changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if dockerfile inline changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Dockerfile = &Dockerfile{Inline: "FROM scratch"} return a }, wantChanges: true, }, { - name: "diff if platforms change", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if platforms change", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Platforms = []Platform{"linux/amd64"} return a }, wantChanges: true, }, { - name: "diff if pull changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if pull changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Pull = true return a }, wantChanges: true, }, { - name: "diff if builder changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if builder changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Builder = &BuilderConfig{Name: "foo"} return a }, wantChanges: true, }, { - name: "diff if tags change", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if tags change", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Tags = []string{"foo"} return a }, wantChanges: true, }, { - name: "diff if exports change", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if exports change", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Exports = []Export{{Raw: "foo"}} return a }, wantChanges: true, }, { - name: "diff if target changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if target changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Target = "foo" return a }, wantChanges: true, }, { - name: "diff if pulling", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if pulling", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Pull = true return a }, wantChanges: true, }, { - name: "diff if noCache changes", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if noCache changes", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.NoCache = true return a }, wantChanges: true, }, { - name: "diff if labels change", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if labels change", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Labels = map[string]string{"foo": "bar"} return a }, wantChanges: true, }, { - name: "diff if secrets change", - olds: func(*testing.T, ImageState) ImageState { return baseState }, - news: func(_ *testing.T, a ImageArgs) ImageArgs { + name: "diff if secrets change", + state: func(*testing.T, ImageState) ImageState { return baseState }, + inputs: func(_ *testing.T, a ImageArgs) ImageArgs { a.Secrets = map[string]string{"foo": "bar"} return a }, @@ -762,13 +751,13 @@ func TestImageDiff(t *testing.T) { }, { name: "diff if local export doesn't exist", - olds: func(t *testing.T, state ImageState) ImageState { + state: func(t *testing.T, state ImageState) ImageState { state.Exports = []Export{ {Local: &ExportLocal{Dest: "not-real"}}, } return state }, - news: func(_ *testing.T, args ImageArgs) ImageArgs { + inputs: func(_ *testing.T, args ImageArgs) ImageArgs { args.Exports = []Export{ {Local: &ExportLocal{Dest: "not-real"}}, } @@ -778,13 +767,13 @@ func TestImageDiff(t *testing.T) { }, { name: "diff if tar export doesn't exist", - olds: func(t *testing.T, state ImageState) ImageState { + state: func(t *testing.T, state ImageState) ImageState { state.Exports = []Export{ {Tar: &ExportTar{ExportLocal: ExportLocal{Dest: "not-real"}}}, } return state }, - news: func(_ *testing.T, args ImageArgs) ImageArgs { + inputs: func(_ *testing.T, args ImageArgs) ImageArgs { args.Exports = []Export{ {Tar: &ExportTar{ExportLocal: ExportLocal{Dest: "not-real"}}}, } @@ -794,12 +783,12 @@ func TestImageDiff(t *testing.T) { }, } - s := newServer(nil) + s := newServer(t.Context(), t, nil) - encode := func(t *testing.T, x any) resource.PropertyMap { + encode := func(t *testing.T, x any) property.Map { raw, err := mapper.New(&mapper.Opts{IgnoreMissing: true}).Encode(x) require.NoError(t, err) - return resource.NewPropertyMapFromMap(raw) + return resource.FromResourcePropertyMap(resource.NewPropertyMapFromMap(raw)) } for _, tt := range tests { @@ -808,9 +797,9 @@ func TestImageDiff(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() resp, err := s.Diff(provider.DiffRequest{ - Urn: _fakeURN, - Olds: encode(t, tt.olds(t, baseState)), - News: encode(t, tt.news(t, baseArgs)), + Urn: _fakeURN, + State: encode(t, tt.state(t, baseState)), + Inputs: encode(t, tt.inputs(t, baseArgs)), }) assert.NoError(t, err) assert.Equal(t, tt.wantChanges, resp.HasChanges, resp.DetailedDiff) diff --git a/provider/internal/index.go b/provider/internal/index.go index 516f7d6..3cbae69 100644 --- a/provider/internal/index.go +++ b/provider/internal/index.go @@ -28,7 +28,6 @@ import ( provider "github.com/pulumi/pulumi-go-provider" "github.com/pulumi/pulumi-go-provider/infer" - "github.com/pulumi/pulumi/sdk/v3/go/common/resource" ) var ( @@ -47,7 +46,10 @@ var ( var _indexExamples string // Index is an OCI index or manifest list on a remote registry. -type Index struct{} +type Index struct { + clientF clientF + config *Config +} // IndexArgs instantiate an Index. type IndexArgs struct { @@ -64,6 +66,14 @@ func (i IndexArgs) isPushed() bool { return *i.Push } +// GetRegistries returns the index's registry. +func (i IndexArgs) GetRegistries() []Registry { + if i.Registry == nil { + return nil + } + return []Registry{*i.Registry} +} + // IndexState captures the state of an Index. type IndexState struct { IndexArgs @@ -132,66 +142,82 @@ func (i *IndexState) Annotate(a infer.Annotator) { // Create is a passthrough to Update. func (i *Index) Create( ctx context.Context, - name string, - input IndexArgs, - preview bool, -) (string, IndexState, error) { - state, err := i.Update(ctx, name, IndexState{}, input, preview) - return name, state, err + req infer.CreateRequest[IndexArgs], +) (infer.CreateResponse[IndexState], error) { + resp, err := i.Update(ctx, + infer.UpdateRequest[IndexArgs, IndexState]{ + ID: req.Name, + State: IndexState{}, + Inputs: req.Inputs, + DryRun: req.DryRun, + }, + ) + return infer.CreateResponse[IndexState]{ID: req.Name, Output: resp.Output}, err } // Update performs `buildx imagetools create` to create a new OCI index / // manifest list. func (i *Index) Update( ctx context.Context, - name string, - state IndexState, - input IndexArgs, - preview bool, -) (IndexState, error) { + req infer.UpdateRequest[IndexArgs, IndexState], +) (infer.UpdateResponse[IndexState], error) { + state, input := req.State, req.Inputs + state.IndexArgs = input state.Ref = input.Tag - cli, err := i.client(ctx, state, input) + cli, err := i.client(ctx, input) if err != nil { - return state, err + return infer.UpdateResponse[IndexState]{Output: state}, err } - if preview { - return state, nil + if req.DryRun { + return infer.UpdateResponse[IndexState]{Output: state}, nil } - provider.GetLogger(ctx).Debugf("creating index with tag %s and sources %s", input.Tag, input.Sources) + provider.GetLogger(ctx). + Debugf("creating index with tag %s and sources %s", input.Tag, input.Sources) err = cli.ManifestCreate(ctx, input.isPushed(), input.Tag, input.Sources...) if err != nil { - return state, fmt.Errorf("creating: %w", err) + return infer.UpdateResponse[IndexState]{Output: state}, fmt.Errorf("creating: %w", err) } - _, _, state, err = i.Read(ctx, name, input, state) + // Read remote manifest information, if it exists. + live, err := i.Read(ctx, + infer.ReadRequest[IndexArgs, IndexState]{ID: req.ID, Inputs: input, State: state}, + ) if err != nil { - return state, fmt.Errorf("reading: %w", err) + return infer.UpdateResponse[IndexState]{Output: state}, fmt.Errorf("reading: %w", err) } - return state, nil + return infer.UpdateResponse[IndexState]{Output: live.State}, nil } func (i *Index) Read( ctx context.Context, - name string, - input IndexArgs, - state IndexState, -) (string, IndexArgs, IndexState, error) { + req infer.ReadRequest[IndexArgs, IndexState], +) (infer.ReadResponse[IndexArgs, IndexState], error) { + state, input := req.State, req.Inputs + state.IndexArgs = input state.Ref = input.Tag if !input.isPushed() { provider.GetLogger(ctx).Debug("skipping read because index was not pushed") - return name, input, state, nil // Nothing to read. + return infer.ReadResponse[IndexArgs, IndexState]{ + ID: req.ID, + Inputs: input, + State: state, + }, nil // Nothing to read. } - cli, err := i.client(ctx, state, input) + cli, err := i.client(ctx, input) if err != nil { - return name, input, state, err + return infer.ReadResponse[IndexArgs, IndexState]{ + ID: req.ID, + Inputs: input, + State: state, + }, err } provider.GetLogger(ctx).Debug("reading index with tag " + input.Tag) @@ -199,21 +225,29 @@ func (i *Index) Read( digest, err := cli.ManifestInspect(ctx, input.Tag) if errors.Is(err, errs.ErrNotFound) { // A remote tag was expected but isn't there -- delete the resource. - return "", input, state, nil + return infer.ReadResponse[IndexArgs, IndexState]{ID: "", Inputs: input, State: state}, nil } if errors.Is(err, errs.ErrHTTPUnauthorized) { provider.GetLogger(ctx).Warning("invalid credentials, skipping") - return name, input, state, nil + return infer.ReadResponse[IndexArgs, IndexState]{ + ID: req.ID, + Inputs: input, + State: state, + }, nil } if err != nil { - return name, input, state, err + return infer.ReadResponse[IndexArgs, IndexState]{ + ID: req.ID, + Inputs: input, + State: state, + }, err } if ref, ok := addDigest(input.Tag, digest); ok { state.Ref = ref } - return name, input, state, nil + return infer.ReadResponse[IndexArgs, IndexState]{ID: req.ID, Inputs: input, State: state}, nil } // Check confirms the Index's tag and source refs are all valid. This doesn't @@ -222,13 +256,11 @@ func (i *Index) Read( // cases for now. func (i *Index) Check( ctx context.Context, - _ string, - _ resource.PropertyMap, - news resource.PropertyMap, -) (IndexArgs, []provider.CheckFailure, error) { - args, failures, err := infer.DefaultCheck[IndexArgs](ctx, news) + req infer.CheckRequest, +) (infer.CheckResponse[IndexArgs], error) { + args, failures, err := infer.DefaultCheck[IndexArgs](ctx, req.NewInputs) if err != nil { - return args, failures, err + return infer.CheckResponse[IndexArgs]{Failures: failures, Inputs: args}, err } if _, err := normalizeReference(args.Tag); args.Tag != "" && err != nil { @@ -253,27 +285,31 @@ func (i *Index) Check( } } - return args, failures, nil + return infer.CheckResponse[IndexArgs]{Failures: failures, Inputs: args}, nil } // Delete attempts to delete the remote manifest. -func (i *Index) Delete(ctx context.Context, _ string, state IndexState) error { +func (i *Index) Delete( + ctx context.Context, + req infer.DeleteRequest[IndexState], +) (infer.DeleteResponse, error) { + state := req.State if !state.isPushed() { - return nil // Nothing to delete. + return infer.DeleteResponse{}, nil // Nothing to delete. } - cli, err := i.client(ctx, state, state.IndexArgs) + cli, err := i.client(ctx, state.IndexArgs) if err != nil { - return err + return infer.DeleteResponse{}, err } err = cli.ManifestDelete(ctx, state.Ref) // TODO: Upstream buildx swallows the error types we'd like to test for // here. if err != nil && strings.Contains(err.Error(), "No such manifest:") { - return nil + return infer.DeleteResponse{}, nil } - return err + return infer.DeleteResponse{}, err } // Diff returns a diff of proposed changes against current state. Ideally we @@ -282,10 +318,10 @@ func (i *Index) Delete(ctx context.Context, _ string, state IndexState) error { // change all the time due to short-lived AWS credentials). func (i *Index) Diff( _ context.Context, - _ string, - olds IndexState, - news IndexArgs, + req infer.DiffRequest[IndexArgs, IndexState], ) (provider.DiffResponse, error) { + olds, news := req.State, req.Inputs + diff := map[string]provider.PropertyDiff{} update := provider.PropertyDiff{Kind: provider.Update} replace := provider.PropertyDiff{Kind: provider.UpdateReplace} @@ -323,23 +359,7 @@ func (i *Index) Diff( // any host-level credentials. func (i *Index) client( ctx context.Context, - _ IndexState, args IndexArgs, ) (Client, error) { - cfg := infer.GetConfig[Config](ctx) - - if cli, ok := ctx.Value(_mockClientKey).(Client); ok { - return cli, nil - } - - // We prefer auth from args, the provider, and state in that order. We - // build a slice in reverse order because wrap() will overwrite earlier - // entries with later ones. - auths := []Registry{} - auths = append(auths, cfg.Registries...) - if args.Registry != nil { - auths = append(auths, *args.Registry) - } - - return wrap(cfg.host, auths...) + return i.clientF(ctx, i.config.getHost(), i.config, args) } diff --git a/provider/internal/index_test.go b/provider/internal/index_test.go index 96773ec..5da04f3 100644 --- a/provider/internal/index_test.go +++ b/provider/internal/index_test.go @@ -27,34 +27,35 @@ import ( "github.com/pulumi/pulumi-go-provider/integration" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" "github.com/pulumi/pulumi/sdk/v3/go/common/util/mapper" + "github.com/pulumi/pulumi/sdk/v3/go/property" ) func TestIndexLifecycle(t *testing.T) { t.Parallel() - realClient := func(t *testing.T) Client { return nil } + realClient := func(t *testing.T) clientF { return RealClientF } tests := []struct { name string skip bool op func(t *testing.T) integration.Operation - client func(t *testing.T) Client + client func(t *testing.T) clientF }{ { name: "not pushed", client: realClient, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "tag": resource.NewStringProperty( + Inputs: property.NewMap(map[string]property.Value{ + "tag": property.New( "docker.io/pulumibot/buildkit-e2e:manifest-unit", ), - "sources": resource.NewArrayProperty([]resource.PropertyValue{ - resource.NewStringProperty("docker.io/pulumibot/buildkit-e2e:arm64"), - resource.NewStringProperty("docker.io/pulumibot/buildkit-e2e:amd64"), + "sources": property.New([]property.Value{ + property.New("docker.io/pulumibot/buildkit-e2e:arm64"), + property.New("docker.io/pulumibot/buildkit-e2e:amd64"), }), - "push": resource.NewBoolProperty(false), - }, + "push": property.New(false), + }), } }, }, @@ -64,59 +65,51 @@ func TestIndexLifecycle(t *testing.T) { client: realClient, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "tag": resource.NewStringProperty( + Inputs: property.NewMap(map[string]property.Value{ + "tag": property.New( "docker.io/pulumibot/buildkit-e2e:manifest", ), - "sources": resource.NewArrayProperty([]resource.PropertyValue{ - resource.NewStringProperty("docker.io/pulumibot/buildkit-e2e:arm64"), - resource.NewStringProperty("docker.io/pulumibot/buildkit-e2e:amd64"), + "sources": property.New([]property.Value{ + property.New("docker.io/pulumibot/buildkit-e2e:arm64"), + property.New("docker.io/pulumibot/buildkit-e2e:amd64"), }), - "push": resource.NewBoolProperty(true), - "registry": resource.NewObjectProperty(resource.PropertyMap{ - "address": resource.NewStringProperty("docker.io"), - "username": resource.NewStringProperty("pulumibot"), - "password": resource.NewSecretProperty(&resource.Secret{ - Element: resource.NewStringProperty( - os.Getenv("DOCKER_HUB_PASSWORD"), - ), - }), + "push": property.New(true), + "registry": property.New(map[string]property.Value{ + "address": property.New("docker.io"), + "username": property.New("pulumibot"), + "password": property.New(os.Getenv("DOCKER_HUB_PASSWORD")).WithSecret(true), }), - }, + }), } }, }, { name: "expired credentials", - client: func(t *testing.T) Client { + client: func(t *testing.T) clientF { ctrl := gomock.NewController(t) c := NewMockClient(ctrl) c.EXPECT().ManifestCreate(gomock.Any(), true, gomock.Any(), gomock.Any()) c.EXPECT().ManifestInspect(gomock.Any(), gomock.Any()).Return("", errs.ErrHTTPUnauthorized) c.EXPECT().ManifestDelete(gomock.Any(), gomock.Any()).Return(nil) - return c + return mockClientF(c) }, op: func(t *testing.T) integration.Operation { return integration.Operation{ - Inputs: resource.PropertyMap{ - "tag": resource.NewStringProperty( + Inputs: property.NewMap(map[string]property.Value{ + "tag": property.New( "docker.io/pulumibot/buildkit-e2e:manifest", ), - "sources": resource.NewArrayProperty([]resource.PropertyValue{ - resource.NewStringProperty("docker.io/pulumibot/buildkit-e2e:arm64"), - resource.NewStringProperty("docker.io/pulumibot/buildkit-e2e:amd64"), + "sources": property.New([]property.Value{ + property.New("docker.io/pulumibot/buildkit-e2e:arm64"), + property.New("docker.io/pulumibot/buildkit-e2e:amd64"), }), - "push": resource.NewBoolProperty(true), - "registry": resource.NewObjectProperty(resource.PropertyMap{ - "address": resource.NewStringProperty("docker.io"), - "username": resource.NewStringProperty("pulumibot"), - "password": resource.NewSecretProperty(&resource.Secret{ - Element: resource.NewStringProperty( - os.Getenv("DOCKER_HUB_PASSWORD"), - ), - }), + "push": property.New(true), + "registry": property.New(map[string]property.Value{ + "address": property.New("docker.io"), + "username": property.New("pulumibot"), + "password": property.New(os.Getenv("DOCKER_HUB_PASSWORD")).WithSecret(true), }), - }, + }), } }, }, @@ -132,7 +125,7 @@ func TestIndexLifecycle(t *testing.T) { Resource: "docker-build:index:Index", Create: tt.op(t), } - s := newServer(tt.client(t)) + s := newServer(t.Context(), t, tt.client(t)) err := s.Configure(provider.ConfigureRequest{}) require.NoError(t, err) @@ -149,22 +142,22 @@ func TestIndexDiff(t *testing.T) { baseState := IndexState{IndexArgs: baseArgs} tests := []struct { - name string - olds func(*testing.T, IndexState) IndexState - news func(*testing.T, IndexArgs) IndexArgs + name string + state func(*testing.T, IndexState) IndexState + inputs func(*testing.T, IndexArgs) IndexArgs wantChanges bool }{ { name: "no diff if no changes", - olds: func(*testing.T, IndexState) IndexState { return baseState }, - news: func(*testing.T, IndexArgs) IndexArgs { return baseArgs }, + state: func(*testing.T, IndexState) IndexState { return baseState }, + inputs: func(*testing.T, IndexArgs) IndexArgs { return baseArgs }, wantChanges: false, }, { - name: "diff if tag changes", - olds: func(*testing.T, IndexState) IndexState { return baseState }, - news: func(t *testing.T, a IndexArgs) IndexArgs { + name: "diff if tag changes", + state: func(*testing.T, IndexState) IndexState { return baseState }, + inputs: func(t *testing.T, a IndexArgs) IndexArgs { a.Tag = "new-tag" return a }, @@ -172,7 +165,7 @@ func TestIndexDiff(t *testing.T) { }, { name: "no diff if registry password changes", - olds: func(_ *testing.T, s IndexState) IndexState { + state: func(_ *testing.T, s IndexState) IndexState { s.Registry = &Registry{ Address: "foo", Username: "foo", @@ -180,7 +173,7 @@ func TestIndexDiff(t *testing.T) { } return s }, - news: func(_ *testing.T, a IndexArgs) IndexArgs { + inputs: func(_ *testing.T, a IndexArgs) IndexArgs { a.Registry = &Registry{ Address: "foo", Username: "foo", @@ -191,9 +184,9 @@ func TestIndexDiff(t *testing.T) { wantChanges: false, }, { - name: "diff if registry added", - olds: func(*testing.T, IndexState) IndexState { return baseState }, - news: func(_ *testing.T, a IndexArgs) IndexArgs { + name: "diff if registry added", + state: func(*testing.T, IndexState) IndexState { return baseState }, + inputs: func(_ *testing.T, a IndexArgs) IndexArgs { a.Registry = &Registry{Address: "foo.com", Username: "foo", Password: "foo"} return a }, @@ -201,7 +194,7 @@ func TestIndexDiff(t *testing.T) { }, { name: "diff if registry user changes", - olds: func(_ *testing.T, s IndexState) IndexState { + state: func(_ *testing.T, s IndexState) IndexState { s.Registry = &Registry{ Address: "foo", Username: "foo", @@ -209,7 +202,7 @@ func TestIndexDiff(t *testing.T) { } return s }, - news: func(_ *testing.T, a IndexArgs) IndexArgs { + inputs: func(_ *testing.T, a IndexArgs) IndexArgs { a.Registry = &Registry{ Address: "DIFFERENT USER", Username: "foo", @@ -221,21 +214,21 @@ func TestIndexDiff(t *testing.T) { }, } - s := newServer(nil) + s := newServer(t.Context(), t, nil) - encode := func(t *testing.T, x any) resource.PropertyMap { + encode := func(t *testing.T, x any) property.Map { raw, err := mapper.New(&mapper.Opts{IgnoreMissing: true}).Encode(x) require.NoError(t, err) - return resource.NewPropertyMapFromMap(raw) + return resource.FromResourcePropertyMap(resource.NewPropertyMapFromMap(raw)) } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() resp, err := s.Diff(provider.DiffRequest{ - Urn: urn, - Olds: encode(t, tt.olds(t, baseState)), - News: encode(t, tt.news(t, baseArgs)), + Urn: urn, + State: encode(t, tt.state(t, baseState)), + Inputs: encode(t, tt.inputs(t, baseArgs)), }) assert.NoError(t, err) assert.Equal(t, tt.wantChanges, resp.HasChanges, resp.DetailedDiff) diff --git a/provider/internal/provider.go b/provider/internal/provider.go index 92c232f..e3265a3 100644 --- a/provider/internal/provider.go +++ b/provider/internal/provider.go @@ -45,9 +45,6 @@ type Config struct { host *host } -// _mockClientKey is used by tests to inject a mock Docker client. -var _mockClientKey any = "mock-client" - // Annotate provides user-facing descriptions and defaults for Config's fields. func (c *Config) Annotate(a infer.Annotator) { a.Describe(&c.Host, "The build daemon's address.") @@ -64,8 +61,23 @@ func (c *Config) Configure(ctx context.Context) error { return nil } +// GetRegistries returns the config's registries, if any. +func (c Config) GetRegistries() []Registry { + return c.Registries +} + +// getHost returns the config's host, or nil if the config is also nil. +func (c *Config) getHost() *host { + if c == nil { + return nil + } + return c.host +} + // NewBuildxProvider returns a new buildx provider. -func NewBuildxProvider() provider.Provider { +func NewBuildxProvider(clientF clientF) provider.Provider { + config := &Config{} + prov := infer.Provider( infer.Options{ Metadata: pschema.Metadata{ @@ -113,41 +125,22 @@ func NewBuildxProvider() provider.Provider { }, }, Resources: []infer.InferredResource{ - infer.Resource[*Image](), - infer.Resource[*Index](), + infer.Resource(&Image{clientF: clientF, config: config}), + infer.Resource(&Index{clientF: clientF, config: config}), }, ModuleMap: map[tokens.ModuleName]tokens.ModuleName{ "internal": "index", }, - Config: infer.Config[*Config](), + 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. func Schema(ctx context.Context, version string) schema.PackageSpec { - p := NewBuildxProvider() + p := NewBuildxProvider(nil) spec, err := provider.GetSchema(ctx, "docker-build", version, p) contract.AssertNoErrorf(err, "missing schema") return spec diff --git a/provider/internal/provider_test.go b/provider/internal/provider_test.go index 2436fae..f1bbe50 100644 --- a/provider/internal/provider_test.go +++ b/provider/internal/provider_test.go @@ -20,18 +20,18 @@ import ( "github.com/blang/semver" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" provider "github.com/pulumi/pulumi-go-provider" "github.com/pulumi/pulumi-go-provider/infer" "github.com/pulumi/pulumi-go-provider/integration" - mwcontext "github.com/pulumi/pulumi-go-provider/middleware/context" "github.com/pulumi/pulumi/sdk/v3/go/common/tokens" ) func TestConfigure(t *testing.T) { t.Parallel() - s := newServer(nil) + s := newServer(t.Context(), t, nil) err := s.Configure( provider.ConfigureRequest{}, @@ -60,7 +60,7 @@ func TestAnnotate(t *testing.T) { func TestSchema(t *testing.T) { t.Parallel() - s := newServer(nil) + s := newServer(t.Context(), t, nil) _, err := s.GetSchema(provider.GetSchemaRequest{Version: 0}) assert.NoError(t, err) @@ -68,21 +68,27 @@ func TestSchema(t *testing.T) { type annotator struct{} +func (annotator) Deprecate(_ any, _ string) {} func (annotator) Describe(_ any, _ string) {} func (annotator) SetDefault(_, _ any, _ ...string) {} func (annotator) SetToken(tokens.ModuleName, tokens.TypeName) {} func (annotator) AddAlias(tokens.ModuleName, tokens.TypeName) {} func (annotator) SetResourceDeprecationMessage(_ string) {} -func newServer(client Client) integration.Server { - p := NewBuildxProvider() +func newServer(ctx context.Context, t *testing.T, clientF clientF) integration.Server { + t.Helper() - // Inject a mock client if provided. - if client != nil { - p = mwcontext.Wrap(p, func(ctx context.Context) context.Context { - return context.WithValue(ctx, _mockClientKey, client) - }) + if clientF == nil { + clientF = RealClientF } - return integration.NewServer("docker-build", semver.Version{Major: 0}, p) + p := NewBuildxProvider(clientF) + + s, err := integration.NewServer( + ctx, + "docker-build", semver.Version{Major: 0}, + integration.WithProvider(p), + ) + require.NoError(t, err) + return s } diff --git a/provider/provider.go b/provider/provider.go index 5d157aa..982cec4 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -15,13 +15,8 @@ package provider import ( - "context" - "encoding/json" - "github.com/pulumi/pulumi-docker-build/provider/internal" - "github.com/pulumi/pulumi-docker-build/provider/internal/deprecated" gp "github.com/pulumi/pulumi-go-provider" - "github.com/pulumi/pulumi/pkg/v3/codegen/schema" "github.com/pulumi/pulumi/pkg/v3/resource/provider" rpc "github.com/pulumi/pulumi/sdk/v3/proto/go" ) @@ -39,37 +34,5 @@ func Serve() error { // New creates a new provider. func New(host *provider.HostClient) (rpc.ResourceProviderServer, error) { - return gp.RawServer(Name, Version, configurableProvider(internal.NewBuildxProvider()))(host) -} - -// configurableProvider is a workaround for -// https://github.com/pulumi/pulumi-go-provider/issues/171 and -// In short, our SDKs send provider Configure requests as simple strings -// instead of rich objects. We don't want to preserve this behavior in -// pulumi-go-provider, but we also haven't updated SDKs yet to send rich types. -// -// If you find yourself in a position where you need to copy this -- STOP! -// https://github.com/pulumi/pulumi/pull/15032 should be merged with this fix. -func configurableProvider(p gp.Provider) gp.Provider { - configure := p.Configure - - p.Configure = func(ctx context.Context, req gp.ConfigureRequest) error { - r, err := p.GetSchema(ctx, gp.GetSchemaRequest{Version: 0}) - if err != nil { - return err - } - spec := schema.PackageSpec{} - err = json.Unmarshal([]byte(r.Schema), &spec) - if err != nil { - return err - } - - ce := deprecated.New(spec.Config) - if props, err := ce.UnmarshalProperties(req.Args); err == nil { - req.Args = props - } - return configure(ctx, req) - } - - return p + return gp.RawServer(Name, Version, internal.NewBuildxProvider(internal.RealClientF))(host) } diff --git a/provider/provider_test.go b/provider/provider_test.go index 81e0d06..c92e634 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -22,37 +22,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" emptypb "google.golang.org/protobuf/types/known/emptypb" - "google.golang.org/protobuf/types/known/structpb" - - "github.com/pulumi/pulumi-docker-build/provider/internal" - provider "github.com/pulumi/pulumi-go-provider" - "github.com/pulumi/pulumi-go-provider/integration" - "github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin" ) -// TestConfigure checks backwards-compatibility with SDKs that still send -// provider config as JSON-encoded strings. This test can be removed once we -// upgrade to a version of pulumi that no longer generates SDKs with that -// behavior. -func TestConfigure(t *testing.T) { - t.Parallel() - - p := configurableProvider(internal.NewBuildxProvider()) - - args, err := structpb.NewStruct(map[string]any{ - "registries": `[{"address": "docker.io"}]`, - }) - require.NoError(t, err) - argsMap, err := plugin.UnmarshalProperties(args, plugin.MarshalOptions{}) - require.NoError(t, err) - - s := integration.NewServer("docker-build", semver.Version{Major: 0}, p) - err = s.Configure(provider.ConfigureRequest{ - Args: argsMap, - }) - assert.NoError(t, err) -} - func TestVersion(t *testing.T) { t.Parallel() diff --git a/sdk/go/dockerbuild/go.mod b/sdk/go/dockerbuild/go.mod index 9269ea4..be6aecb 100644 --- a/sdk/go/dockerbuild/go.mod +++ b/sdk/go/dockerbuild/go.mod @@ -4,7 +4,7 @@ go 1.24.1 require ( github.com/blang/semver v3.5.1+incompatible - github.com/pulumi/pulumi/sdk/v3 v3.165.0 + github.com/pulumi/pulumi/sdk/v3 v3.169.0 ) require ( @@ -83,14 +83,14 @@ require ( go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel/sdk v1.35.0 // indirect go.uber.org/atomic v1.11.0 // indirect - golang.org/x/crypto v0.37.0 // indirect + golang.org/x/crypto v0.38.0 // indirect golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect golang.org/x/mod v0.24.0 // indirect - golang.org/x/net v0.39.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/term v0.31.0 // indirect - golang.org/x/text v0.24.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/sync v0.14.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect golang.org/x/tools v0.32.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect google.golang.org/grpc v1.71.1 // indirect diff --git a/sdk/go/dockerbuild/go.sum b/sdk/go/dockerbuild/go.sum index 2f55582..0281c7a 100644 --- a/sdk/go/dockerbuild/go.sum +++ b/sdk/go/dockerbuild/go.sum @@ -162,8 +162,8 @@ github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231 h1:vkHw5I/plNdTr435 github.com/pulumi/appdash v0.0.0-20231130102222-75f619a67231/go.mod h1:murToZ2N9hNJzewjHBgfFdXhZKjY3z5cYC1VXk+lbFE= github.com/pulumi/esc v0.13.0 h1:O2MPR2koScaQ2fXwyer8Q3Dd7z+DCnaDfsgNl5mVNMk= github.com/pulumi/esc v0.13.0/go.mod h1:IIQo6W6Uzajt6f1RW4QvNxIRDlbK3TNQysnrwBHNo3U= -github.com/pulumi/pulumi/sdk/v3 v3.165.0 h1:cglplKZOJDpqH8wa/2J250G9az/sE9eKp9fS2bC+vi8= -github.com/pulumi/pulumi/sdk/v3 v3.165.0/go.mod h1:GAaHrdv3kWJHbzkFFFflGbTBQXUYu6SF1ZCo+O9jo44= +github.com/pulumi/pulumi/sdk/v3 v3.169.0 h1:bgz1fp2rl28khSXgF4FaRQiB9wh3lSKWtzUOGalf+x4= +github.com/pulumi/pulumi/sdk/v3 v3.169.0/go.mod h1:Qhe4dOjqedyLr47kGGnG6ULIbzaPTlmjAvPqNQ1Ollo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -228,8 +228,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= @@ -244,13 +244,13 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -266,16 +266,16 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/sdk/python/pulumi_docker_build/_enums.py b/sdk/python/pulumi_docker_build/_enums.py index a1eff50..2d99e20 100644 --- a/sdk/python/pulumi_docker_build/_enums.py +++ b/sdk/python/pulumi_docker_build/_enums.py @@ -3,7 +3,7 @@ # *** Do not edit by hand unless you're certain you know what you are doing! *** import builtins -import builtins +import pulumi from enum import Enum __all__ = [ @@ -14,6 +14,7 @@ __all__ = [ ] +@pulumi.type_token("docker-build:index:CacheMode") class CacheMode(builtins.str, Enum): MIN = "min" """ @@ -25,6 +26,7 @@ class CacheMode(builtins.str, Enum): """ +@pulumi.type_token("docker-build:index:CompressionType") class CompressionType(builtins.str, Enum): GZIP = "gzip" """ @@ -40,6 +42,7 @@ class CompressionType(builtins.str, Enum): """ +@pulumi.type_token("docker-build:index:NetworkMode") class NetworkMode(builtins.str, Enum): DEFAULT = "default" """ @@ -55,6 +58,7 @@ class NetworkMode(builtins.str, Enum): """ +@pulumi.type_token("docker-build:index:Platform") class Platform(builtins.str, Enum): DARWIN_386 = "darwin/386" DARWIN_AMD64 = "darwin/amd64" diff --git a/sdk/python/pulumi_docker_build/image.py b/sdk/python/pulumi_docker_build/image.py index 25314ba..ec948a8 100644 --- a/sdk/python/pulumi_docker_build/image.py +++ b/sdk/python/pulumi_docker_build/image.py @@ -583,10 +583,8 @@ class ImageArgs: pulumi.set(self, "target", value) +@pulumi.type_token("docker-build:index:Image") class Image(pulumi.CustomResource): - - pulumi_type = "docker-build:index:Image" - @overload def __init__(__self__, resource_name: str, diff --git a/sdk/python/pulumi_docker_build/index.py b/sdk/python/pulumi_docker_build/index.py index 74b4821..142c99c 100644 --- a/sdk/python/pulumi_docker_build/index.py +++ b/sdk/python/pulumi_docker_build/index.py @@ -99,10 +99,8 @@ class IndexArgs: pulumi.set(self, "registry", value) +@pulumi.type_token("docker-build:index:Index") class Index(pulumi.CustomResource): - - pulumi_type = "docker-build:index:Index" - @overload def __init__(__self__, resource_name: str, diff --git a/sdk/python/pulumi_docker_build/provider.py b/sdk/python/pulumi_docker_build/provider.py index 74595b0..4f57d8c 100644 --- a/sdk/python/pulumi_docker_build/provider.py +++ b/sdk/python/pulumi_docker_build/provider.py @@ -56,10 +56,8 @@ class ProviderArgs: pulumi.set(self, "registries", value) +@pulumi.type_token("pulumi:providers:docker-build") class Provider(pulumi.ProviderResource): - - pulumi_type = "pulumi:providers:docker-build" - @overload def __init__(__self__, resource_name: str, diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index 2cfafc6..1865590 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "pulumi_docker_build" description = "A Pulumi provider for building modern Docker images with buildx and BuildKit." - dependencies = ["parver>=0.2.1", "pulumi>=3.142.0,<4.0.0", "semver>=2.8.1", "typing-extensions>=4.11,<5; python_version < \"3.11\""] + dependencies = ["parver>=0.2.1", "pulumi>=3.165.0,<4.0.0", "semver>=2.8.1", "typing-extensions>=4.11,<5; python_version < \"3.11\""] keywords = ["docker", "buildkit", "buildx", "kind/native"] readme = "README.md" requires-python = ">=3.9" diff --git a/tools/tools.go b/tools/tools.go index 2136786..c838eeb 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -6,7 +6,7 @@ package tools import ( _ "github.com/golangci/golangci-lint/cmd/golangci-lint" - _ "github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet" + _ "github.com/pulumi/pulumi-dotnet/pulumi-language-dotnet/v3" _ "github.com/pulumi/pulumi-java/pkg/cmd/pulumi-language-java" _ "github.com/pulumi/pulumi-yaml/cmd/pulumi-converter-yaml" _ "github.com/pulumi/pulumi-yaml/cmd/pulumi-language-yaml"