Callbacks#
The callback system allows programs, or even component libraries, to expose user-authored functions to engine and call them across process boundaries. These functions are defined alongside the rest of the Pulumi program, and run in the same process, but are typically not called directly by user code. Instead they are called by the engine at specific moments of the deployment. This mechanism enables features like resource transforms and resource hooks.
The language SDKs start a gRPC server implementing the 🔌 Callbacks service (for example, _callbacks.py). This server exposes a single method: 📞 Invoke. User-authored functions are registered with this server, and the engine is informed of their existence by calling 📞 RegisterStackTransform or 📞 RegisterResourceHook.
The 📨 Callback message is used to register a callback. It represents a callback reference and contains two essential pieces of information:
target: The gRPC address of the callback service (e.g., the gRPC server started by the language SDK).
token: A unique identifier for the specific function to invoke within that service. Language SDKs typically use UUIDs to ensure uniqueness.
When the engine needs to invoke a callback, it calls 📞 Invoke with a 📨 CallbackInvokeRequest. This message contains the token used to identify a function registered with an SDK’s gRPC callback server.
token The token identifying which function to invoke.
request: A serialized protobuf message containing the arguments. The specific message type depends on the callback type (e.g., 📨 TransformRequest for transforms).
The language host receives the request, looks up the function associated with the token, deserializes the request bytes, invokes the function, and returns a 📨 CallbackInvokeResponse:
response: A serialized protobuf message containing the result (e.g., 📨 TransformResponse for transforms).
The callback 📨 CallbackInvokeRequest and 📨 CallbackInvokeResponse are intentionally generic and untyped at the gRPC layer. This allows the system to support multiple callback types, each with their own request/response message formats serialized into the bytes fields.
The system supports multiple callback types, each with their own request/response message formats:
Resource transforms: 📨 TransformRequest and 📨 TransformResponse
Invoke transforms: 📨 TransformInvokeRequest and 📨 TransformInvokeResponse
Resource hooks: 📨 ResourceHookRequest and 📨 ResourceHookResponse