---
title: Accessing single outputs with Apply
url: /docs/iac/concepts/inputs-outputs/apply/
---
The `apply` method is used to access the plain value of a single [output](/docs/iac/concepts/inputs-outputs/#outputs) and perform operations on it. Because outputs are asynchronous values that only become known after a resource has finished provisioning, you cannot directly access or manipulate their values using standard language operations (like printing or string concatenation). The `apply` method solves this by waiting for the output value to become available and then executing a function with that plain value.

The `apply` method is typically used for:

- [Printing output values](#printing-output-values) for debugging Pulumi programs
- [Accessing nested values](#accessing-nested-output-values) in complex types (outputs that are objects or dictionaries)
- [Transforming an output](#creating-new-output-values) by referencing its plain value
- [Converting inputs to outputs](#converting-inputs-to-outputs) to call `apply` on a value typed as `Input<T>`

For more information about what outputs are and why they are necessary in Pulumi programs, see [Inputs and Outputs](/docs/iac/concepts/inputs-outputs/).

> **Note:** The `apply` method is designed for accessing single output values. If you need to access multiple output values across multiple resources, use Pulumi's [`all` method](/docs/concepts/inputs-outputs/all/) instead.

> **Warning:** Creating resources inside an `apply` should be avoided whenever possible. Resources created inside `apply` will not appear in `pulumi preview` unless the output's value is already known. This means the preview output may not match the actual changes when `pulumi up` is run, making it difficult to understand what changes will be made to your infrastructure.

If you need to create a resource that depends on an output value, pass the output directly as an input to the resource instead of using `apply`. Pulumi will automatically handle the dependency tracking and ensure resources are created in the correct order.

> **Warning:** You cannot create [stack outputs](/docs/iac/concepts/stacks/#outputs) (using `export` in TypeScript/JavaScript, `pulumi.export()` in Python, `ctx.Export()` in Go, etc.) inside an `apply`. Stack outputs must be created at the top level of your Pulumi program. If you need to export a value that depends on an output, you can export the output directly—Pulumi will automatically handle resolving the value when the stack output is accessed.

## Printing output values { search.keywords="pulumi.apply" }

Suppose you want to print the ID of a resource you've created. These kinds of values are outputs - values that cannot be known until after a resource is provisioned. You might try logging the value like you would any other string:

<!-- chooser: language -->
<!-- option: typescript -->

```typescript

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as awsx from "@pulumi/awsx";
```

```typescript
const vpc = new awsx.ec2.Vpc("vpc");
```

console.log(vpc.vpcId);
```

<!-- /option -->

<!-- option: python -->

```python

```python
import pulumi
import pulumi_awsx as awsx
```

```python
vpc = awsx.ec2.Vpc("vpc")
```

print(vpc.vpc_id)
```

<!-- /option -->

<!-- option: go -->

```go

```go
package main

import (
```

    "fmt"

```go
	"github.com/pulumi/pulumi-awsx/sdk/v3/go/awsx/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {

```

```go
		vpc, err := ec2.NewVpc(ctx, "vpc", nil)
		if err != nil {
			return err
		}
```

        fmt.Println(vpc.VpcId)

```go
		return nil
	})
}
```

```

<!-- /option -->

<!-- option: csharp -->

```csharp

```csharp
﻿using Pulumi;
using System.Collections.Generic;
using Pulumi.Awsx.Ec2;

return await Deployment.RunAsync(() =>
{
```

```csharp
var vpc = new Vpc("vpc");
```

    Console.WriteLine(vpc.VpcId);

```csharp
});
```

```

<!-- /option -->

<!-- option: java -->

```java

```java
package myproject;

import com.pulumi.Pulumi;
import com.pulumi.awsx.ec2.Vpc;

public class App {
public static void main(String[] args) {
Pulumi.run(ctx -> {

```

```java
var vpc = new Vpc("vpc");
```

            System.out.println(vpc.vpcId());

```java
});
}
}
```

```

<!-- /option -->
<!-- /chooser -->

However, if you run the program as shown with `pulumi up`, you will receive something like the following CLI output:

<!-- chooser: language -->
<!-- option: typescript -->

```bash
# Example CLI output (truncated)
Diagnostics:
  pulumi:pulumi:Stack (aws-js-dev):
    OutputImpl {
      __pulumiOutput: true,
      resources: [Function (anonymous)],
      allResources: [Function (anonymous)],
      isKnown: Promise {  },
      isSecret: Promise {  },
      promise: [Function (anonymous)],
      toString: [Function (anonymous)],
      toJSON: [Function (anonymous)]
    }
```

<!-- /option -->

<!-- option: python -->

```bash
# Example CLI output (truncated)
Diagnostics:
  pulumi:pulumi:Stack (aws-iac-dev):
    Calling __str__ on an Output[T] is not supported.
    To get the value of an Output[T] as an Output[str] consider:
    1. o.apply(lambda v: f"prefix{v}suffix")
    See https://www.pulumi.com/docs/concepts/inputs-outputs for more details.
    This function may throw in a future version of Pulumi.
```

<!-- /option -->

<!-- option: go -->

```bash
# Example CLI output (truncated)
Diagnostics:
  pulumi:pulumi:Stack (aws-go-dev):
    {0xc000137180}
```

<!-- /option -->

<!-- option: csharp -->

```bash
# Example CLI output (truncated)
Diagnostics:
  pulumi:pulumi:Stack (aws-csharp-dev):
    Calling [ToString] on an [Output<T>] is not supported.
    To get the value of an Output<T> as an Output<string> consider:
    1. o.Apply(v => $"prefix{v}suffix")
    2. Output.Format($"prefix{hostname}suffix");
    See https://www.pulumi.com/docs/concepts/inputs-outputs for more details.
    This function may throw in a future version of Pulumi.
```

<!-- /option -->

<!-- option: java -->

```bash
# Example CLI output (truncated)
Updating (pulumi/dev)
    Type                                          Name           Status              Info
 +   pulumi:pulumi:Stack                           aws-java-dev     created (1s)        391 messages
 +   └─ awsx:ec2:Vpc                               vpc            created (1s)
...
...

# Nothing is printed

Resources:
    + 34 created

Duration: 2m17s
```

<!-- /option -->

<!-- option: yaml -->

```yaml
This example is not applicable in YAML.
```

<!-- /option -->
<!-- /chooser -->

This is where <!-- chooser: language -->
<!-- option: javascript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: typescript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: python -->
[`apply`](/docs/reference/pkg/python/pulumi/#pulumi.Output.apply)
<!-- /option -->
<!-- option: go -->
[`Apply`](https://godoc.org/github.com/pulumi/pulumi/sdk/v3/go/pulumi#Output.Apply)
<!-- /option -->
<!-- option: csharp -->
`Apply`
<!-- /option -->
<!-- /chooser -->
 comes into play: When a Pulumi program is executed with `pulumi up`, the <!-- chooser: language -->
<!-- option: javascript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: typescript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: python -->
[`apply`](/docs/reference/pkg/python/pulumi/#pulumi.Output.apply)
<!-- /option -->
<!-- option: go -->
[`Apply`](https://godoc.org/github.com/pulumi/pulumi/sdk/v3/go/pulumi#Output.Apply)
<!-- /option -->
<!-- option: csharp -->
`Apply`
<!-- /option -->
<!-- /chooser -->
 function will wait for the resource to be created and for its properties to be resolved before printing the desired value of the property.

To print out the value of the VPC ID, use the `apply` function:

<!-- chooser: language -->
<!-- option: typescript -->

```typescript

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as awsx from "@pulumi/awsx";
```

```typescript
const vpc = new awsx.ec2.Vpc("vpc");
```

vpc.vpcId.apply(id => console.log(`VPC ID: ${id}`));
```

<!-- /option -->

<!-- option: python -->

```python

```python
import pulumi
import pulumi_awsx as awsx
```

```python
vpc = awsx.ec2.Vpc("vpc")
```

vpc.vpc_id.apply(lambda id: print('VPC ID:', id))
```

<!-- /option -->

<!-- option: go -->

```go

```go
package main

import (
```

    "fmt"

```go
	"github.com/pulumi/pulumi-awsx/sdk/v3/go/awsx/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {

```

```go
		vpc, err := ec2.NewVpc(ctx, "vpc", nil)
		if err != nil {
			return err
		}
```

        vpc.VpcId().ApplyT(func(id string) error {
            fmt.Printf("VPC ID: %s", id)
        	return nil
        })

```go
		return nil
	})
}
```

```

> **Note:** The function `ApplyT` spawns a Goroutine to await the availability of the implicated dependencies. This function accepts a `T` or `(T, error)` signature; the latter accommodates for error handling. Alternatively, one may use the `ApplyTWithContext` function in which the provided context can be used to reject the output as canceled. Error handling may also be achieved using an `error` `chan`.

<!-- /option -->

<!-- option: csharp -->

```csharp

```csharp
﻿using Pulumi;
using System.Collections.Generic;
using Pulumi.Awsx.Ec2;

return await Deployment.RunAsync(() =>
{
```

```csharp
var vpc = new Vpc("vpc");
```

    vpc.VpcId.Apply(id => { Console.WriteLine($"VPC ID: {id}"); return id; });

```csharp
});
```

```

<!-- /option -->

<!-- option: java -->

```java

```java
package myproject;

import com.pulumi.Pulumi;
import com.pulumi.awsx.ec2.Vpc;

public class App {
public static void main(String[] args) {
Pulumi.run(ctx -> {

```

```java
var vpc = new Vpc("vpc");
```

            vpc.vpcId().applyValue(i -> {
                System.out.println("VPC ID: " + i);
                return null;
            });

```java
});
}
}
```

```

<!-- /option -->

<!-- option: yaml -->

```yaml
# YAML does not have the Apply method, but you can access values directly.

```yaml
name: awsx-vpc-yaml
runtime: yaml
description: An example that creates a new VPC using the default settings.
resources:
```

```yaml
  vpc:
type: awsx:ec2:Vpc
```

```yaml
outputs:
```

```yaml
  vpcId: ${vpc.vpcId}
```

```

<!-- /option -->
<!-- /chooser -->

The above example will wait for the value to be returned from the API and print it to the console as shown below:

```bash
Updating (pulumi/dev)

     Type                 Name         Status     Info
     pulumi:pulumi:Stack  aws-iac-dev             1 message

Diagnostics:
  pulumi:pulumi:Stack (aws-iac-dev):
    VPC ID: vpc-0f8a025738f2fbf2f
```

## Accessing nested output values

Sometimes a resource has an output property that is an array or a more complex object multiple levels of nested values. For example, if you created an [AWS Certificate Manager certificate resource](/registry/packages/aws/api-docs/acm/certificate/) as shown below:

<!-- chooser: language -->
<!-- option: typescript -->

```typescript

```typescript
import * as aws from "@pulumi/aws";

const zone = new aws.route53.Zone("zone", {
name: "example.com",
});

const cert = new aws.acm.Certificate("cert", {
domainName: "example.com",
validationMethod: "DNS",
});
```

```

<!-- /option -->

<!-- option: python -->

```python

```python
import pulumi_aws as aws

zone = aws.route53.Zone("zone",
name="example.com",
)

certificate = aws.acm.Certificate("cert",
domain_name="example.com",
validation_method="DNS",
)
```

```

<!-- /option -->

<!-- option: go -->

```go

```go
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/acm"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/route53"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		zone, err := route53.NewZone(ctx, "zone", &route53.ZoneArgs{
			Name: pulumi.String("example.com"),
		})
		if err != nil {
			return err
		}

		cert, err := acm.NewCertificate(ctx, "cert", &acm.CertificateArgs{
			DomainName:       pulumi.String("example.com"),
			ValidationMethod: pulumi.String("DNS"),
		})
		if err != nil {
			return err
		}
```

```

<!-- /option -->

<!-- option: csharp -->

```csharp

```csharp
using Pulumi;
using Pulumi.Aws.Acm;
using Pulumi.Aws.Route53;

return await Deployment.RunAsync(() =>
{
var zone = new Zone("zone", new ZoneArgs
{
Name = "example.com",
});

var cert = new Certificate("cert", new CertificateArgs
{
DomainName = "example.com",
ValidationMethod = "DNS",
});
```

```

<!-- /option -->

<!-- option: java -->

```java

```java
package myproject;

import com.pulumi.Pulumi;
import com.pulumi.aws.acm.Certificate;
import com.pulumi.aws.acm.CertificateArgs;
import com.pulumi.aws.route53.Record;
import com.pulumi.aws.route53.RecordArgs;
import com.pulumi.aws.route53.Zone;
import com.pulumi.aws.route53.ZoneArgs;
import com.pulumi.core.Either;
import java.util.List;

public class App {
public static void main(String[] args) {
Pulumi.run(ctx -> {
var zone = new Zone("zone",
ZoneArgs.builder()
.name("example.com")
.build());

var cert = new Certificate("cert",
CertificateArgs.builder()
.domainName("example.com")
.validationMethod("DNS")
```

```

<!-- /option -->

<!-- option: yaml -->

```yaml

```yaml
name: apply-nested-output-values-yaml
runtime: yaml

resources:
  zone:
type: aws:route53:Zone
properties:
name: example.com

  cert:
type: aws:acm:Certificate
properties:
domainName: example.com
validationMethod: DNS
```

```

<!-- /option -->
<!-- /chooser -->

This resource will have outputs that resemble the following:

```plain
# Example truncated output of the ACM certificate resource
cert: {
    arn                      : "arn:aws:acm:eu-central-1..."
    certificate_authority_arn: ""
    certificate_body         : <null>
    certificate_chain        : <null>
    domain_name              : "example.com"
    domain_validation_options: [[0]: {
            domain_name          : "example.com"
            resource_record_name : "_0a822dde6347292b.example.com."
            resource_record_type : "CNAME"
            resource_record_value: "_527b1cdf2159204b.mhbtsbpdnt.acm-validations.aws."
        }
    ]
    ...
    ...
}
```

Suppose you want to validate your certificate by creating an [Amazon Route 53 record](/registry/packages/aws/api-docs/route53/record/). To do so, you will need to retrieve the value of the resource record from the ACM certificate. This value is nested in the domain validation options property of the certificate resource, which is an array. Because that value is an output, you would normally need to use <!-- chooser: language -->
<!-- option: javascript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: typescript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: python -->
[`apply`](/docs/reference/pkg/python/pulumi/#pulumi.Output.apply)
<!-- /option -->
<!-- option: go -->
[`Apply`](https://godoc.org/github.com/pulumi/pulumi/sdk/v3/go/pulumi#Output.Apply)
<!-- /option -->
<!-- option: csharp -->
`Apply`
<!-- /option -->
<!-- /chooser -->
 to retrieve it:

<!-- chooser: language -->

<!-- option: typescript -->
```typescript

```typescript
// Using apply to access nested output values
const certValidationApply = new aws.route53.Record("certValidationApply", {
name: cert.domainValidationOptions.apply(
domainValidationOptions => domainValidationOptions[0].resourceRecordName),
type: cert.domainValidationOptions.apply(
domainValidationOptions => domainValidationOptions[0].resourceRecordType),
zoneId: zone.zoneId,
ttl: 60,
records: [cert.domainValidationOptions.apply(
domainValidationOptions => domainValidationOptions[0].resourceRecordValue),
],
});

```

```

```

<!-- /option -->

<!-- option: python -->
```python

```python
# Using apply to access nested output values
cert_validation_apply = aws.route53.Record("certValidationApply",
    name=certificate.domain_validation_options.apply(
        lambda domain_validation_options: domain_validation_options[0].resource_record_name
    ),
    type=certificate.domain_validation_options.apply(
        lambda domain_validation_options: domain_validation_options[0].resource_record_type
    ),
    zone_id=zone.zone_id,
    ttl=60,
    records=[certificate.domain_validation_options.apply(
            lambda domain_validation_options: domain_validation_options[0].resource_record_value
        )
    ],
)

```

```

```

<!-- /option -->

<!-- option: go -->
```go

```go
		// Using apply to access nested output values
		_, err = route53.NewRecord(ctx, "certValidationApply", &route53.RecordArgs{
			Name: cert.DomainValidationOptions.ApplyT(func(opts []acm.CertificateDomainValidationOption) string {
return *opts[0].ResourceRecordName
			}).(pulumi.StringOutput),
			Type: cert.DomainValidationOptions.ApplyT(func(opts []acm.CertificateDomainValidationOption) string {
return *opts[0].ResourceRecordType
			}).(pulumi.StringOutput),
			ZoneId: zone.ZoneId,
			Ttl:    pulumi.Int(60),
			Records: pulumi.StringArray{
cert.DomainValidationOptions.ApplyT(func(opts []acm.CertificateDomainValidationOption) string {
return *opts[0].ResourceRecordValue
}).(pulumi.StringOutput),
			},
		})
		if err != nil {
			return err
		}

```

```

```

<!-- /option -->

<!-- option: csharp -->
```csharp

```csharp
    // Using apply to access nested output values
    var certValidationApply = new Record("certValidationApply", new RecordArgs
    {
        Name = cert.DomainValidationOptions.Apply(opts => opts[0].ResourceRecordName!),
        Type = cert.DomainValidationOptions.Apply(opts => opts[0].ResourceRecordType!),
        ZoneId = zone.ZoneId,
        Ttl = 60,
        Records = { cert.DomainValidationOptions.Apply(opts => opts[0].ResourceRecordValue!) },
    });

```

```

```

<!-- /option -->

<!-- option: java -->
```java

```java

// Using apply to access nested output values
var certValidation = new Record("certValidationApply",
RecordArgs.builder()
.name(cert.domainValidationOptions()
.applyValue(opts -> opts.get(0).resourceRecordName().get()))
.type(cert.domainValidationOptions()
.applyValue(opts -> Either.ofLeft(opts.get(0).resourceRecordType().get())))
.zoneId(zone.zoneId())
.ttl(60)
.records(cert.domainValidationOptions()
.applyValue(opts -> opts.get(0).resourceRecordValue().get())
.applyValue(String::valueOf)
.applyValue(List::of))

```

```

```

<!-- /option -->

<!-- option: yaml -->
```yaml
This example is not applicable in YAML.

```

<!-- /option -->

<!-- /chooser -->

### Using lifting to simplify nested access

An easier way to access deeply nested properties is by using _lifting_. Lifting allows you to access properties and elements directly from a <!-- chooser: language -->
<!-- option: javascript -->
[`Output`](/docs/reference/pkg/nodejs/pulumi/pulumi/#Output)
<!-- /option -->
<!-- option: typescript -->
[`Output<T>`](/docs/reference/pkg/nodejs/pulumi/pulumi/#Output)
<!-- /option -->
<!-- option: python -->
[`Output[T]`](/docs/reference/pkg/python/pulumi/#pulumi.Output)
<!-- /option -->
<!-- option: go -->
[`Output`](https://godoc.org/github.com/pulumi/pulumi/sdk/v3/go/pulumi#Output)
<!-- /option -->
<!-- option: csharp -->
`Output<T>`
<!-- /option -->
<!-- /chooser -->
 without needing an <!-- chooser: language -->
<!-- option: javascript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: typescript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: python -->
[`apply`](/docs/reference/pkg/python/pulumi/#pulumi.Output.apply)
<!-- /option -->
<!-- option: go -->
[`Apply`](https://godoc.org/github.com/pulumi/pulumi/sdk/v3/go/pulumi#Output.Apply)
<!-- /option -->
<!-- option: csharp -->
`Apply`
<!-- /option -->
<!-- /chooser -->
.

Lifting is handled automatically by Pulumi's type system, making it largely transparent to use. When you access a property or array element on an output value, Pulumi automatically "lifts" that access into the output context, returning a new output that will resolve to that nested value. 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.

> **Note:** Lifting works in most scenarios for accessing nested properties and array elements. However, you may occasionally encounter runtime errors with lifting depending on your language. For example, in TypeScript, if an output resolves to `undefined`, using lifting to reference `outputThatResolvesToUndefined.someProperty` would cause a runtime error. In such cases, use `apply` with appropriate null checking instead.

Returning to the certificate validation example from the previous section, you can use lifting to simplify the code as shown below:

<!-- chooser: language -->

<!-- option: typescript -->
```typescript

```typescript
// Using lifting to access nested output values
const certValidationLifting = new aws.route53.Record("certValidationLifting", {
    name: cert.domainValidationOptions[0].resourceRecordName,
    type: cert.domainValidationOptions[0].resourceRecordType,
    zoneId: zone.zoneId,
    ttl: 60,
    records: [cert.domainValidationOptions[0].resourceRecordValue,
    ],
});

```

```

```

<!-- /option -->

<!-- option: python -->
```python

```python
# Using lifting to access nested output values
cert_validation_lifting = aws.route53.Record("certValidationLifting",
name=certificate.domain_validation_options[0].resource_record_name,
type=certificate.domain_validation_options[0].resource_record_type,
zone_id=zone.zone_id,
ttl=60,
records=[certificate.domain_validation_options[0].resource_record_value
],
)

```

```

> **Warning:** **Python implementation note**: In Python, output lifting is implemented by overriding the special `__getattr__` method on resources. The expression `resource.output` (which results in a call to `resource.__getattr__("output")`) becomes `resource.apply(lambda r: r.output)`. This means that using `hasattr`, which calls `__getattr__` under the hood and looks for an `AttributeError` to determine whether or not a property exists, will not work as expected on resource outputs.

```

<!-- /option -->

<!-- option: go -->
```go

```go
		// Using lifting to access nested output values
		_, err = route53.NewRecord(ctx, "certValidationLifting", &route53.RecordArgs{
			Name: cert.DomainValidationOptions.Index(pulumi.Int(0)).ResourceRecordName().Elem(),
			Type: cert.DomainValidationOptions.Index(pulumi.Int(0)).ResourceRecordType().Elem(),
			ZoneId: zone.ZoneId,
			Ttl:    pulumi.Int(60),
			Records: pulumi.StringArray{
				cert.DomainValidationOptions.Index(pulumi.Int(0)).ResourceRecordValue().Elem(),
			},
		})
		if err != nil {
			return err
		}

```

```

```

<!-- /option -->

<!-- option: csharp -->
```csharp

```csharp
// Using lifting to access nested output values
var certValidationLifting = new Record("certValidationLifting", new RecordArgs
{
Name = cert.DomainValidationOptions.GetAt(0).Apply(opt => opt.ResourceRecordName!),
Type = cert.DomainValidationOptions.GetAt(0).Apply(opt => opt.ResourceRecordType!),
ZoneId = zone.ZoneId,
Ttl = 60,
Records = { cert.DomainValidationOptions.GetAt(0).Apply(opt => opt.ResourceRecordValue!) },
});

```

```

```

<!-- /option -->

<!-- option: java -->
```java
// Lifting is currently not supported in Java.
// Use apply as shown in the previous section.

```

<!-- /option -->

<!-- option: yaml -->
```yaml

```yaml
  # Using lifting to access nested output values
  certValidation:
    type: aws:route53:Record
    properties:
      name: ${cert.domainValidationOptions[0].resourceRecordName}
      type: ${cert.domainValidationOptions[0].resourceRecordType}
      zoneId: ${zone.zoneId}
      ttl: 60
      records:
        - ${cert.domainValidationOptions[0].resourceRecordValue}

```

```

```

<!-- /option -->

<!-- /chooser -->

## Creating new output values

### Outputs and strings

Outputs that return to the engine as strings cannot be used directly in operations such as string concatenation until the output value has returned to Pulumi. In these scenarios, you'll need to wait for the value to return using [`apply`](/docs/concepts/inputs-outputs/apply/).

> **Note:** For the common case of building a string from output values, Pulumi's [output helpers](/docs/concepts/inputs-outputs/helpers/#string-interpolation) provide a more concise alternative that doesn't require calling `apply` directly.

For example, the following code creates an HTTPS URL from the DNS name (the plain value) of a virtual machine (in this case an EC2 instance):

<!-- chooser: language -->
<!-- option: typescript -->

```typescript

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

```

```typescript
const server = new aws.ec2.Instance("web-server", {
ami: "ami-0319ef1a70c93d5c8",
instanceType: "t2.micro",
```

```typescript
});
```

const url = server.publicDns.apply(dnsName => `https://${dnsName}`);

export const InstanceUrl = url;
```

<!-- /option -->

<!-- option: python -->

```python

```python
import pulumi
import pulumi_aws as aws

```

```python
server = aws.ec2.Instance(
"web-server",
ami="ami-0319ef1a70c93d5c8",
instance_type="t2.micro",
```

```python
)
```

url = server.public_dns.apply(
    lambda dns_name: "https://" + dns_name
)

pulumi.export("InstanceUrl", url)
```

<!-- /option -->

<!-- option: go -->

```go

```go
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
```

```go
		server, err := ec2.NewInstance(ctx, "web-server", &ec2.InstanceArgs{
			Ami:                 pulumi.String("ami-0319ef1a70c93d5c8"),
			InstanceType:        pulumi.String("t2.micro"),
```

```go
		})
		if err != nil {
			return err
		}
```

        url := server.PublicDns.ApplyT(func(dns string) string {
			return "https://" + dns
		}).(pulumi.StringOutput)

        ctx.Export("InstanceUrl", url)

```go
		return nil
	})
}
```

```

<!-- /option -->

<!-- option: csharp -->

```csharp

```csharp
using Pulumi;
using Pulumi.Aws.Ec2;
using Pulumi.Aws.Ec2.Inputs;
using System.Collections.Generic;

return await Deployment.RunAsync(() =>
{
```

```csharp
var server = new Instance("web-server", new InstanceArgs {
Ami = "ami-0319ef1a70c93d5c8",
InstanceType = "t2.micro",
```

```csharp
});
```

    var url = server.PublicDns.Apply(dns => $"https://{dns}");

```csharp
return new Dictionary<string, object?>
{
```

        ["InstanceUrl"] = url,

```csharp
};
});
```

```

<!-- /option -->

<!-- option: java -->

```java

```java
package myproject;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.aws.ec2.Instance;
import com.pulumi.aws.ec2.InstanceArgs;
import com.pulumi.aws.ec2.SecurityGroup;
import com.pulumi.aws.ec2.SecurityGroupArgs;
import com.pulumi.aws.ec2.inputs.SecurityGroupIngressArgs;

import java.util.List;

public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}

public static void stack(Context ctx) {
```

```java
var server = new Instance("web-server",
InstanceArgs.builder()
.ami("ami-0319ef1a70c93d5c8")
.instanceType("t2.micro")
```

```java
.build());
```

        var url = server.publicDns().applyValue(dns -> "https://" + dns);

        ctx.export("InstanceUrl", url);

```java
}
}
```

```

<!-- /option -->

<!-- option: yaml -->

```yaml
# YAML does not have the Apply method, but you can access values directly.
name: aws-ec2-instance-yaml

```yaml
runtime: yaml
description: An example that shows how to create an EC2 instance and security group.
resources:
```

```yaml
  server:
type: aws:ec2:Instance
properties:
ami: ami-0319ef1a70c93d5c8
instanceType: t2.micro
```

```yaml
outputs:
```

  InstanceUrl: https://${server.publicDns}
```

<!-- /option -->
<!-- /chooser -->

The CLI output of this code would look something like the following:

```bash
Updating (pulumi/dev)

     Type                 Name         Status
     pulumi:pulumi:Stack  aws-iac-dev
 -   └─ awsx:ec2:Vpc      vpc

Outputs:
    InstanceUrl: "https://ec2-52-59-110-22.eu-central-1.compute.amazonaws.com"

Duration: 5s
```

The returned value of the call to <!-- chooser: language -->
<!-- option: javascript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: typescript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: python -->
[`apply`](/docs/reference/pkg/python/pulumi/#pulumi.Output.apply)
<!-- /option -->
<!-- option: go -->
[`Apply`](https://godoc.org/github.com/pulumi/pulumi/sdk/v3/go/pulumi#Output.Apply)
<!-- /option -->
<!-- option: csharp -->
`Apply`
<!-- /option -->
<!-- /chooser -->
 is a new `pulumi.Output<string>`, meaning the `url` variable is now of an Output. This variable will wait for the new value to be returned from the <!-- chooser: language -->
<!-- option: javascript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: typescript -->
[`apply`](/docs/reference/pkg/nodejs/pulumi/pulumi/#OutputInstance-apply)
<!-- /option -->
<!-- option: python -->
[`apply`](/docs/reference/pkg/python/pulumi/#pulumi.Output.apply)
<!-- /option -->
<!-- option: go -->
[`Apply`](https://godoc.org/github.com/pulumi/pulumi/sdk/v3/go/pulumi#Output.Apply)
<!-- /option -->
<!-- option: csharp -->
`Apply`
<!-- /option -->
<!-- /chooser -->
 function, and any dependencies of the original output (i.e. the `public DNS` property of the `server` resource) are also kept in the resulting `pulumi.Output<string>`.

### Outputs and JSON

Many cloud resources require JavaScript Object Notation (JSON) documents, such as policies that control access to resources. The Pulumi SDK provides helper methods in most languages to make it easier to work with Pulumi outputs and JSON documents. These helper methods have similar names and function signatures to their plain-value analogues. For a consolidated reference of all JSON helpers, see [Using output helpers](/docs/concepts/inputs-outputs/helpers/#json-helpers).

#### Converting JSON objects to strings

If you need to construct a JSON string using output values from Pulumi resources, you can do so using a JSON stringify helper that is defined in the Pulumi SDK. These helpers unwrap Pulumi outputs without requiring the use of `apply` and produce JSON string outputs suitable for passing to other resources as inputs.

The following example demonstrates using helper methods for JSON serialization:

<!-- chooser: language -->

<!-- option: typescript -->

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// Get the account ID of the current user as a Pulumi output.
const accountID = aws.getCallerIdentityOutput().accountId;

// Create an S3 bucket.
const bucket = new aws.s3.Bucket("my-bucket");

// Create an S3 bucket policy allowing anyone in the account to list the contents of the bucket.
const policy = new aws.s3.BucketPolicy("my-bucket-policy", {
    bucket: bucket.id,
    policy: pulumi.jsonStringify({
        Version: "2012-10-17",
        Statement: [{
                Effect: "Allow",
                Principal: {
                    AWS: pulumi.interpolate`arn:aws:iam::${accountID}:root`,
                },
                Action: "s3:ListBucket",
                Resource: bucket.arn,
            },
        ],
    }),
});

// Export the name of the bucket.
export const bucketName = bucket.id;

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-s3-bucketpolicy-jsonstringify-typescript)

<!-- /option -->

<!-- option: python -->

```python
import pulumi
import pulumi_aws as aws

# Get the account ID of the current user as a Pulumi output.
account_id = aws.get_caller_identity_output().apply(
    lambda identity: identity.account_id
)

# Create an S3 bucket.
bucket = aws.s3.Bucket("my-bucket")

# Create an S3 bucket policy allowing anyone in the account to list the contents of the bucket.
policy = aws.s3.BucketPolicy(
    "my-bucket-policy",
    bucket=bucket.id,
    policy=pulumi.Output.json_dumps(
        {
            "Version": "2012-10-17",
            "Statement": [{
                    "Effect": "Allow",
                    "Principal": {
                        "AWS": pulumi.Output.format("arn:aws:iam::{0}:root", account_id)
                    },
                    "Action": "s3:ListBucket",
                    "Resource": bucket.arn,
                }
            ],
        }
    ),
)

# Export the name of the bucket
pulumi.export("bucketName", bucket.id)

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-s3-bucketpolicy-jsonstringify-python)

<!-- /option -->

<!-- option: go -->

```go
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {

		// Get the account ID of the current user as a Pulumi Output.
		callerIdentity, err := aws.GetCallerIdentity(ctx, nil, nil)
		if err != nil {
			return err
		}
		accountID := callerIdentity.AccountId

		// Create an AWS resource (S3 Bucket)
		bucket, err := s3.NewBucket(ctx, "my-bucket", nil)
		if err != nil {
			return err
		}

		// Create an S3 bucket policy allowing anyone in the account to list the contents of the bucket.
		_, err = s3.NewBucketPolicy(ctx, "my-bucket-policy", &s3.BucketPolicyArgs{
			Bucket: bucket.ID(),
			Policy: pulumi.JSONMarshal(map[string]interface{}{
				"Version": pulumi.ToOutput("2012-10-17"),
				"Statement": pulumi.ToOutput([]interface{}{
					pulumi.ToMapOutput(map[string]pulumi.Output{
						"Effect": pulumi.ToOutput("Allow"),
						"Principal": pulumi.ToMapOutput(map[string]pulumi.Output{
							"AWS": pulumi.Sprintf("arn:aws:iam::%s:root", accountID),
						}),
						"Action":   pulumi.ToOutput("s3:ListBucket"),
						"Resource": bucket.Arn,
					}),
				}),
			}),
		})
		if err != nil {
			return err
		}

		// Export the name of the bucket
		ctx.Export("bucketName", bucket.ID())
		return nil
	})
}

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-s3-bucketpolicy-jsonstringify-go)

<!-- /option -->

<!-- option: csharp -->

```csharp
﻿using System.Collections.Generic;
using Pulumi;
using Pulumi.Aws.S3;

return await Deployment.RunAsync(() =>
{
    // Get the account ID of the current user as a Pulumi output.
    var accountID = Pulumi.Aws.GetCallerIdentity.Invoke().Apply(identity => identity.AccountId);

    // Create an S3 bucket.
    var bucket = new Bucket("my-bucket");

    // Create an S3 bucket policy allowing anyone in the account to list the contents of the bucket.
    var policy = new BucketPolicy("my-bucket-policy", new BucketPolicyArgs
        {
            Bucket = bucket.Id,
            Policy = Output.JsonSerialize(Output.Create(
                new
                {
                    Version = "2012-10-17",
                    Statement = new[]
                    {
                        new
                        {
                            Effect = "Allow",
                            Principal = new
                            {
                                AWS = Output.Format($"arn:aws:iam::{accountID}:root")
                            },
                            Action = "s3:ListBucket",
                            Resource = bucket.Arn,
                        }
                    }
                }
            ))
        }
    );

    // Export the name of the bucket.
    return new Dictionary<string, object?> { ["bucketName"] = bucket.Id };
});

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-s3-bucketpolicy-jsonstringify-csharp)

<!-- /option -->

<!-- /chooser -->

When constructing a JSON policy document, it is often necessary to build a resource identifier by appending a path suffix to an output value. For example, Amazon S3 bucket policies that apply to objects rather than to the bucket itself require a resource ARN ending in `/*`. Because the bucket ARN is a Pulumi output, you must combine the JSON stringify helper with your language's string interpolation facility to produce the correct value.

The following example demonstrates this pattern, using the bucket's ARN as a base and appending `/*` to target all objects in the bucket:

<!-- chooser: language -->

<!-- option: javascript -->

```javascript
"use strict";
const pulumi = require("@pulumi/pulumi");
const aws = require("@pulumi/aws");

// Create an S3 bucket.
const bucket = new aws.s3.Bucket("my-bucket");

// Create an S3 bucket policy that grants read access to all objects in the bucket.
// The Resource field uses pulumi.interpolate to append "/*" to the bucket ARN,
// targeting individual objects rather than the bucket itself.
const policy = new aws.s3.BucketPolicy("my-bucket-policy", {
    bucket: bucket.id,
    policy: pulumi.jsonStringify({
        Version: "2012-10-17",
        Statement: [{
                Effect: "Allow",
                Principal: "*",
                Action: "s3:GetObject",
                Resource: pulumi.interpolate`${bucket.arn}/*`,
            },
        ],
    }),
});

// Export the name of the bucket.
exports.bucketName = bucket.id;

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-s3-bucketpolicy-jsonstringify-interpolate-javascript)

<!-- /option -->

<!-- option: typescript -->

```typescript
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// Create an S3 bucket.
const bucket = new aws.s3.Bucket("my-bucket");

// Create an S3 bucket policy that grants read access to all objects in the bucket.
// The Resource field uses pulumi.interpolate to append "/*" to the bucket ARN,
// targeting individual objects rather than the bucket itself.
const policy = new aws.s3.BucketPolicy("my-bucket-policy", {
    bucket: bucket.id,
    policy: pulumi.jsonStringify({
        Version: "2012-10-17",
        Statement: [{
                Effect: "Allow",
                Principal: "*",
                Action: "s3:GetObject",
                Resource: pulumi.interpolate`${bucket.arn}/*`,
            },
        ],
    }),
});

// Export the name of the bucket.
export const bucketName = bucket.id;

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-s3-bucketpolicy-jsonstringify-interpolate-typescript)

<!-- /option -->

<!-- option: python -->

```python
import pulumi
import pulumi_aws as aws

# Create an S3 bucket.
bucket = aws.s3.Bucket("my-bucket")

# Create an S3 bucket policy that grants read access to all objects in the bucket.
# The Resource field uses pulumi.Output.concat to append "/*" to the bucket ARN,
# targeting individual objects rather than the bucket itself.
policy = aws.s3.BucketPolicy(
    "my-bucket-policy",
    bucket=bucket.id,
    policy=pulumi.Output.json_dumps(
        {
            "Version": "2012-10-17",
            "Statement": [{
                    "Effect": "Allow",
                    "Principal": "*",
                    "Action": "s3:GetObject",
                    "Resource": pulumi.Output.concat(bucket.arn, "/*"),
                }
            ],
        }
    ),
)

# Export the name of the bucket.
pulumi.export("bucketName", bucket.id)

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-s3-bucketpolicy-jsonstringify-interpolate-python)

<!-- /option -->

<!-- option: go -->

```go
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {

		// Create an S3 bucket.
		bucket, err := s3.NewBucket(ctx, "my-bucket", nil)
		if err != nil {
			return err
		}

		// Create an S3 bucket policy that grants read access to all objects in the bucket.
		// The Resource field uses pulumi.Sprintf to append "/*" to the bucket ARN,
		// targeting individual objects rather than the bucket itself.
		_, err = s3.NewBucketPolicy(ctx, "my-bucket-policy", &s3.BucketPolicyArgs{
			Bucket: bucket.ID(),
			Policy: pulumi.JSONMarshal(map[string]interface{}{
				"Version": pulumi.ToOutput("2012-10-17"),
				"Statement": pulumi.ToOutput([]interface{}{
					pulumi.ToMapOutput(map[string]pulumi.Output{
						"Effect":    pulumi.ToOutput("Allow"),
						"Principal": pulumi.ToOutput("*"),
						"Action":    pulumi.ToOutput("s3:GetObject"),
						"Resource":  pulumi.Sprintf("%s/*", bucket.Arn),
					}),
				}),
			}),
		})
		if err != nil {
			return err
		}

		// Export the name of the bucket.
		ctx.Export("bucketName", bucket.ID())
		return nil
	})
}

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-s3-bucketpolicy-jsonstringify-interpolate-go)

<!-- /option -->

<!-- option: csharp -->

```csharp
using System.Collections.Generic;
using Pulumi;
using Pulumi.Aws.S3;

return await Deployment.RunAsync(() =>
{
    // Create an S3 bucket.
    var bucket = new Bucket("my-bucket");

    // Create an S3 bucket policy that grants read access to all objects in the bucket.
    // The Resource field uses Output.Format to append "/*" to the bucket ARN,
    // targeting individual objects rather than the bucket itself.
    var policy = new BucketPolicy("my-bucket-policy", new BucketPolicyArgs
        {
            Bucket = bucket.Id,
            Policy = Output.JsonSerialize(Output.Create(
                new
                {
                    Version = "2012-10-17",
                    Statement = new[]
                    {
                        new
                        {
                            Effect = "Allow",
                            Principal = "*",
                            Action = "s3:GetObject",
                            Resource = Output.Format($"{bucket.Arn}/*"),
                        }
                    }
                }
            ))
        }
    );

    // Export the name of the bucket.
    return new Dictionary<string, object?> { ["bucketName"] = bucket.Id };
});

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-s3-bucketpolicy-jsonstringify-interpolate-csharp)

<!-- /option -->

<!-- /chooser -->

#### Converting JSON strings to outputs

If you have an output in the form of a JSON string and you need to interact with it like you would a regular JSON object, you can use Pulumi's parsing helper function.

The following example shows how to use a helper method to parse an IAM policy defined as a `pulumi.Output<string>` into a native object and then manipulate that object to remove all of the policy statements:

<!-- chooser: language -->

<!-- option: typescript -->

```typescript
import * as pulumi from "@pulumi/pulumi";

const jsonIAMPolicy = pulumi.output(`{
    "Version": "2012-10-17",
    "Statement": [{
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": ["s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::my-bucket"
        }
    ]
}`);

// Parse the string output.
const policyWithNoStatements: pulumi.Output<object> = pulumi.jsonParse(jsonIAMPolicy).apply(policy => {
    // Empty the policy's Statements list.
    policy.Statement = [];
    return policy;
});

// Export the modified policy.
export const policy = policyWithNoStatements;

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-iampolicy-jsonparse-typescript)

<!-- /option -->

<!-- option: python -->

```python
import pulumi

json_iam_policy = pulumi.Output.from_input(
    """
{
    "Version": "2012-10-17",
    "Statement": [{
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": ["s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::my-bucket"
        }
    ]
}
"""
)

def update_policy(policy):
    # Empty the policy's Statements list.
    policy.update({"Statement": []})
    return policy

# Parse the string output.
policy_with_no_statements = pulumi.Output.json_loads(json_iam_policy).apply(
    lambda policy: update_policy
)

# Export the modified policy.
pulumi.export("policy", policy_with_no_statements)

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-iampolicy-jsonparse-python)

<!-- /option -->

<!-- option: go -->

```go
package main

import (
	"encoding/json"
	
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {

		jsonIAMPolicy := pulumi.ToOutput(`{
		    "Version": "2012-10-17",
		    "Statement": [{
		            "Sid": "VisualEditor0",
		            "Effect": "Allow",
		            "Action": ["s3:ListAllMyBuckets",
		                "s3:GetBucketLocation"
		            ],
		            "Resource": "*"
		        },
		        {
		            "Sid": "VisualEditor1",
		            "Effect": "Allow",
		            "Action": "s3:*",
		            "Resource": "arn:aws:s3:::my-bucket"
		        }
		    ]
		}`)

		// Parse the string output.
		policyWithNoStatements := jsonIAMPolicy.ApplyT(
			func(jsonStr string) (map[string]interface{}, error) {
				var policy map[string]interface{}
				if err := json.Unmarshal([]byte(jsonStr), &policy); err != nil {
					return nil, err
				}

				// Empty the policy's Statements list.
				policy["Statement"] = []interface{}{}
				return policy, nil
			},
		)

		// Export the modified policy.
		ctx.Export("policy", policyWithNoStatements)
		return nil
	})
}

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-iampolicy-jsonparse-go)

<!-- /option -->

<!-- option: csharp -->

```csharp
using System.Collections.Generic;
using Pulumi;

return await Deployment.RunAsync(() =>
{
    var jsonIAMPolicy = Output.Create(
        @"
        {
            ""Version"": ""2012-10-17"",
            ""Statement"": [{
                    ""Sid"": ""VisualEditor0"",
                    ""Effect"": ""Allow"",
                    ""Action"": [""s3:ListAllMyBuckets"",
                        ""s3:GetBucketLocation""
                    ],
                    ""Resource"": ""*""
                },
                {
                    ""Sid"": ""VisualEditor1"",
                    ""Effect"": ""Allow"",
                    ""Action"": [""s3:*""
                    ],
                    ""Resource"": ""arn:aws:s3:::my-bucket""
                }
            ]
        }
    "
    );

    // Parse the Output<string> into a C# Dictionary.
    var policyWithNoStatements = Output
        .JsonDeserialize<Dictionary<string, object?>>(jsonIAMPolicy)
        .Apply(policy =>
        {
            // Empty the policy's Statements list.
            policy["Statement"] = new List<object?>();
            return policy;
        });

    // Export the modified policy.
    return new Dictionary<string, object?> { ["policy"] = policyWithNoStatements, };
});

```

[View full example on GitHub](https://github.com/pulumi/docs/tree/master/static/programs/aws-iampolicy-jsonparse-csharp)

<!-- /option -->

<!-- /chooser -->

<!-- chooser: language -->
<!-- option: typescript -->

For more details [view the Node.js documentation](/docs/reference/pkg/nodejs/pulumi/pulumi/).

<!-- /option -->

<!-- option: python -->

For more details [view the Python documentation](/docs/reference/pkg/python/pulumi/).

<!-- /option -->

<!-- option: go -->

For more details [view the Go documentation](https://pkg.go.dev/github.com/pulumi/pulumi/sdk/v3/go/pulumi).

<!-- /option -->

<!-- option: csharp -->

For more details [view the .NET documentation](/docs/reference/pkg/dotnet/pulumi/pulumi.output.html).

<!-- /option -->
<!-- /chooser -->

## Converting inputs to outputs

Resource arguments in Pulumi accept `Input<T>` values, which means they will take either a plain value or an `Output<T>`. In most programs this flexibility is all you need. There are situations, however, where you have a value typed as `Input<T>` and need to ensure it is a definite `Output<T>`—most commonly to call `apply` on it.

This situation arises most often in the following cases:

- **Writing a component resource.** Component constructors typically accept `Input<T>` parameters to give callers the flexibility to pass either a plain value or an existing output. Inside the component body, you often need to call `apply` or chain other output operations on those parameters, which requires `Output<T>`.
- **Writing utility functions that accept `Input<T>`.** A function that accepts `Input<T>` for caller flexibility must convert to `Output<T>` internally before it can call `apply` to perform any transformation.
- **Combining values with `all`.** While the `all` function accepts a mix of plain values and outputs in most SDKs, explicitly converting to outputs first can make your program’s data flow clearer and more predictable.

Pulumi's SDKs provide a dedicated function to wrap any `Input<T>` as a guaranteed `Output<T>`:

<!-- chooser: language -->

<!-- option: typescript -->
`pulumi.output()` accepts any <code>Input<T></code>—a plain value or an existing <code>Output<T></code>—and returns <code>Output<T></code>. The example below defines a helper that requires <code>Output<string></code> internally, then calls it with both a plain string and with an <code>Output<string></code> from a resource to show that both work.
```typescript
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

function buildUrl(host: pulumi.Input<string>): pulumi.Output<string> {
    return pulumi.output(host).apply(h => `https://${h}`);
}

const fromPlain = buildUrl("example.com");

const bucket = new aws.s3.BucketV2("my-bucket");
const fromOutput = buildUrl(bucket.websiteEndpoint);

```

<!-- /option -->

<!-- option: python -->
`pulumi.Output.from_input()` accepts any `Input[T]`—a plain value or an existing `Output[T]`—and returns `Output[T]`.
```python
import pulumi
import pulumi_aws as aws

# A helper function that accepts Input[str] but needs to call apply.
def build_url(host: pulumi.Input[str]) -> pulumi.Output[str]:
    return pulumi.Output.from_input(host).apply(lambda h: f"https://{h}")

# Works with a plain string.
from_plain = build_url("example.com")

# Works equally well with an Output[str] from a resource.
bucket = aws.s3.BucketV2("my-bucket")
from_output = build_url(bucket.website_endpoint)

```

<!-- /option -->

<!-- option: go -->
In Go, each typed input interface exposes a `ToXxxOutput()` method that returns the corresponding concrete output type. For example, `pulumi.StringInput` provides `ToStringOutput()`. The snippet below defines a helper that requires `pulumi.StringOutput` internally, then calls it with both a plain value and a `StringOutput` from a resource.
```go
import (
    awss3 "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/s3"
    "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func buildURL(input pulumi.StringInput) pulumi.StringOutput {
    return input.ToStringOutput().ApplyT(func(host string) string {
        return "https://" + host
    }).(pulumi.StringOutput)
}

// Inside a Pulumi program:
fromPlain := buildURL(pulumi.String("example.com"))

bucket, _ := awss3.NewBucketV2(ctx, "my-bucket", nil, nil)
fromOutput := buildURL(bucket.Bucket)

```

Each typed input interface in the Go SDK—`pulumi.StringInput`, `pulumi.IntInput`, `pulumi.BoolInput`, and so on—follows this same `ToXxxOutput()` pattern.

<!-- /option -->

<!-- option: csharp -->
In C#, <code>Input<T></code> exposes `Apply` through Pulumi SDK extension methods, so you can often call `Apply` without an explicit conversion step:
```csharp
// Input<T> supports Apply through extension methods in the Pulumi C# SDK.
Input<string> host = "example.com"; // could be a plain string or Output<string>
Output<string> url = host.Apply(h => $"https://{h}");

```

When you need to construct a standalone <code>Output<T></code> from a plain value, use `Output.Create`:
```csharp
Output<string> output = Output.Create("example.com");

```

<!-- /option -->

<!-- option: java -->
`Output.of()` wraps a plain value as an <code>Output<T></code>. When your value is already an <code>Output<T></code>, you can use it directly without any conversion.
```java
import com.pulumi.core.Output;

Output<String> output = Output.of("example.com");
Output<String> url = output.applyValue(host -> "https://" + host);

```

<!-- /option -->

<!-- /chooser -->

When the value you pass is already an `Output<T>`, the conversion function returns it unchanged. When you pass a plain value, Pulumi wraps it in a new output that resolves immediately with that value. In either case, the result is a definite `Output<T>` on which you can call `apply` or any other output method.

