Day 6 - Pulumi Inputs and Outputs

Day 6 - Pulumi Inputs and Outputs

Day 6 - Pulumi Input and Outputs

What are Inputs and Outputs?

All resources args in Pulumi can accept Inputs; Inputs are values of type Input<T>, a kind that permits either a raw value of a given type like string, integer, boolean, list, map, and so on.

Here is an example of AWS S3 bucket Inputs, to name a few.


All resource properties on the instance object itself are outputs. Outputs are values of type Output<T>.

If we can a look at the Pulumi documentation for [AWS S3](aws.s3.Bucket | Pulumi buckets; we can see that we have the following list of Outputs.


How can we use Inputs and Outputs?

In the following ComponentResource we can see that we are setting Outputs to both Id and Name; When creating an instance of this class we will now have access to Id and Name that we could in turn now pass into another class that we may need to storage account Id for.

A good example of this in the Azure space is with LogAnalytics we need to have a storage account to point a location to where we would like to have our Logs archived!

public class StorageAccount : ComponentResource  
public Output<string> Id { get; private set; }  

public Output<string> Name { get; private set; }  

    public PrivateStorageAccount(string name, PrivateStorageAccountArgs args,  
        ComponentResourceOptions? options = null, bool remote = false) :  
        base("StorageAccount", name, args, options, remote)  
    {        var storageAccount = new StorageAccount($"{name}", new StorageAccountArgs  
            AccountName = name.Replace("-",""),  
            Kind = Kind.StorageV2,  
            Sku = new SkuArgs  
                Name = SkuName.Standard_GRS  
            AllowBlobPublicAccess = args.AllowBlobPublicAccess,  
            EnableHttpsTrafficOnly = true,  
            Location = args.ResourceGroupLocation,  
            MinimumTlsVersion = MinimumTlsVersion.TLS1_2,  
            ResourceGroupName = args.ResourceGroupName,  
            Tags = args.Tags,  
        new CustomResourceOptions  
            Parent = this  
        Id = storageAccount.Id;  
        Name = storageAccount.Name;  

By passing output from one resource as an input to another resource, Pulumi captures dependencies automatically. When these dependencies are captured, physical infrastructure resources will not be created or updated until all their dependencies are available and current.

It is not possible to obtain the actual raw values of outputs immediately due to their asynchronous nature. If you need to access an output’s raw value—for example, to compute a derived, new value, or because you want to log it—you have these options:

Apply: a callback that receives the raw value, and computes a new output

Lifting: directly read the properties of an output value

Interpolation: concatenate string outputs with other strings directly

Using Apply

Use Apply to access the raw value of output and transform that value into a new value. This method accepts a callback that will be invoked with the raw value, once that value is available.

Here we can see how we would grab the DNS name of a VM and apply this to a URL format.

var url = virtualmachine.DnsName.Apply(dnsName => "https://" + dnsName);

Access an Output by Lifting

If you need to use the value of a property as an argument in another resource's constructor, you can usually just access Output directly.

var cert = new Certificate("cert", new CertificateArgs
    DomainName = "example",
    ValidationMethod = "DNS",

var record = new Record("validation", new RecordArgs
    // Notes:
    // * `GetAt` looks up an index in an `Output<ImmutableArray<T>>` and returns a new `Output<T>`
    // * There are not yet accessor methods for referencing properties like `ResourceRecordValue` on an `Output<T>` directly,
    //   so the `Apply` is still needed for the property access.
    Records = cert.DomainValidationOptions.GetAt(0).Apply(opt => opt.ResourceRecordValue!),

This approach doesn’t work in all cases, but when it does this approach is easier to read and write and does not lose any important dependency information that is needed to properly create and maintain the stack, it can be a great help.

Outputs and Strings.

Say you want to create a URL from the hostname and port output values. You can do this using apply and all or we can use Output.Format

// Format takes a FormattableString and expands outputs correctly:
var url = Output.Format($"http://{hostname}:{port}/");

Why Inputs and Outputs?

Certain values are not available to us at runtime; this is where Inputs and Outputs come into play! They can help us set and access values that we need for other resources somewhere after runtime.

We have different options to use when we are facing this issue; so don't forget to reference the Inputs & Outputs

Happy coding my friends!

Did you find this article valuable?

Support Jordan Taylor by becoming a sponsor. Any amount is appreciated!