Provider functions
A provider may make functions available in its SDK as well as resource types. These “provider functions” are often for calling a platform API to get a value that is not part of a resource.
For example, the AWS provider includes the function aws.ecs.getAmi
:
import * as aws from "@pulumi/aws";
// Wrapping our program in an immediately invoked async function allows us to
// use the "async" keyword.
(async () => {
const latestAmi = await aws.ec2.getAmi({
owners: ["amazon"],
mostRecent: true,
filters: [
{ name: "name", values: ["amzn2-ami-hvm-*"] },
{ name: "architecture", values: ["x86_64"] }
]
});
new aws.ec2.Instance("web-server", {
ami: latestAmi.imageId,
instanceType: "t3.micro",
});
})();
import pulumi_aws as aws
latest_ami = aws.ec2.get_ami(
owners=["amazon"],
most_recent=True,
filters=[
{"name": "name", "values": ["amzn2-ami-hvm-*"]},
{"name": "architecture", "values": ["x86_64"]}
]
)
instance = aws.ec2.Instance(
"web-server",
ami=latest_ami.image_id,
instance_type="t3.micro"
)
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ec2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
latestAmi, err := ec2.LookupAmi(ctx, &ec2.LookupAmiArgs{
Owners: []string{"amazon"},
MostRecent: pulumi.BoolRef(true),
Filters: []ec2.GetAmiFilter{
{
Name: "name",
Values: []string{"amzn2-ami-hvm-*"},
},
{
Name: "architecture",
Values: []string{"x86_64"},
},
},
}, nil)
if err != nil {
return err
}
_, err = ec2.NewInstance(ctx, "web-server", &ec2.InstanceArgs{
Ami: pulumi.String(latestAmi.ImageId),
InstanceType: pulumi.String("t3.micro"),
})
if err != nil {
return err
}
return nil
})
}
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var latestAmi = Aws.Ec2.GetAmi.Invoke(new Aws.Ec2.GetAmiInvokeArgs
{
Owners = { "amazon" },
MostRecent = true,
Filters =
{
new Aws.Ec2.Inputs.GetAmiFilterInputArgs
{
Name = "name",
Values = { "amzn2-ami-hvm-*" }
},
new Aws.Ec2.Inputs.GetAmiFilterInputArgs
{
Name = "architecture",
Values = { "x86_64" }
}
}
});
var instance = new Aws.Ec2.Instance("web-server", new Aws.Ec2.InstanceArgs
{
Ami = latestAmi.Apply(ami => ami.ImageId),
InstanceType = "t3.micro"
});
});
package myproject;
import com.pulumi.*;
import com.pulumi.aws.ec2.Ec2Functions;
import com.pulumi.aws.ec2.Instance;
import com.pulumi.aws.ec2.InstanceArgs;
import com.pulumi.aws.ec2.inputs.GetAmiArgs;
import com.pulumi.aws.ec2.inputs.GetAmiFilterArgs;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var latestAmi = Ec2Functions.getAmi(GetAmiArgs.builder()
.owners("amazon")
.mostRecent(true)
.filters(
GetAmiFilterArgs.builder()
.name("name")
.values("amzn2-ami-hvm-*")
.build(),
GetAmiFilterArgs.builder()
.name("architecture")
.values("x86_64")
.build())
.build());
new Instance("web-server", InstanceArgs.builder()
.ami(latestAmi.applyValue(ami -> ami.imageId()))
.instanceType("t3.micro")
.build());
}
}
name: provider-functions
runtime: yaml
variables:
lastestAmi:
fn::invoke:
function: aws:ec2/getAmi:getAmi
arguments:
filters:
- name: name
values: ["amzn2-ami-hvm-*"]
- name: architecture
values: ["x86_64"]
owners: ["amazon"]
mostRecent: true
resources:
myInstance:
type: aws:ec2:Instance
properties:
ami: ${lastestAmi.imageId}
instanceType: "t3.micro"
Direct form and output form
Provider functions are exposed in each language as regular functions, in two variations:
- The direct form accepts plain arguments (e.g.,
string
, as opposed topulumi.Input<string>
) and returns an asynchronous value (e.g., aPromise
in Node.js, aTask
in Python, etc.) or blocks until the result is available. These functions are typically named, e.g.,getX()
. - The output form accepts Pulumi Inputs (or plain values) as arguments and returns a Pulumi Output as a result. For more information on these types, see Inputs and Outputs. These functions are typically named, e.g.,
getXOutput()
.
The Pulumi Registry contains authoritative documentation for all provider functions.
Invoke options
In addition to function arguments, provider functions also accept “invoke options”, similar to the way Pulumi resources accept resource options. Invoke options may be specified either as an object or as a list of arguments depending on the language you’re writing your Pulumi program in. The available options are:
dependsOn
: An array of resources that this function depends on. This option is only available in the Output form of a provider function. See Choosing between direct form and output form for a full explanation.parent
: Supply a parent resource for this function call. Much like the parent resource option, the parent will be consulted when determining the provider to use.provider
: Pass an explicitly configured provider to use for this function call, instead of using the default provider. This is useful, for example, if you want to invoke a function in each of a set of AWS regions.
The following options are also available, but are deprecated and should not be used in modern Pulumi programs as the functionality they control are commonly handled when you install a provider package:
pluginDownloadURL
: Pass a URL from which the provider plugin should be fetched. This may be necessary for third-party packages such as those not hosted at https://get.pulumi.com.version
: Pass a provider plugin version that should be used when invoking the function.async
: This option is deprecated and will be removed in a future release.
When your function will execute
While the direct and output forms of a provider function will both return the same data when they are invoked, the two forms differ in when they are executed when running your Pulumi program:
- Direct form functions execute just like any other function call in your Pulumi program’s language. Since direct form functions do not accept Pulumi Inputs and Outputs, they are not tracked by the Pulumi engine the way resources are, and do not participate in the dependency graph.
- Output form functions are tracked by the Pulumi engine because they take Inputs as arguments and return Outputs as return values and therefore participate in the dependency graph. This means that Pulumi will ensure that all input values to the function are resolved before the function is invoked. (This is why
dependsOn
is only an option for the output form of a function.)
Choosing between direct form and output form
There are several common scenarios where either direct form or output form must or should be used:
- If you need a provider function’s result to determine whether a resource should be created at all, you must use the provider function’s the direct form. The direct form of a function executes while the Pulumi engine is formulating the dependency graph (that is, determining what resources need to be created, updated, or deleted), so in order to figure out whether a resource belongs in the graph at all, that decision has to always be calculated up front.
- If you need resources to be created or updated before the function is invoked, you should use the provider function’s output form. (It is possible to use the direct form in this case, but it requires wrapping the call in an
apply
, which can be awkward from a readability standpoint.) Dependencies in the output form of a function are tracked identically to resources: all inputs to the function must be resolved before the function executes. If you need to specify a dependency that isn’t already implied by an input to the function’s arguments, you can use thedependsOn
function option to specify additional dependencies (just like you can with resources).
Pulumi recommends you choose the output form of a function unless you have a specific need for the direct form. We make this recommendation because:
- The output form reduces mental overhead in that it allows your program to stick with a single asynchronous programming mental model (Pulumi inputs and outputs) as opposed to also having to worry about Promises (TypeScript), TaskResults (.NET), etc.
- Syntactically, it’s slightly more terse.
Assuming there is no specific reason to choose one or the other, the choice between the two forms is ultimately a preference: there is no significant difference in either performance or code maintainability between the two forms.
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.