or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asset-management.mdautomation.mdconfiguration.mddynamic-resources.mdindex.mdlogging-diagnostics.mdoutput-system.mdprovider-development.mdresource-management.mdruntime-operations.mdstack-references.mdutilities.md

output-system.mddocs/

0

# Output System

1

2

Pulumi's Output system provides async value management with dependency tracking, enabling safe composition of promises and resource dependencies throughout infrastructure code. Outputs represent values that may not be available until deployment time.

3

4

## Core Output Types

5

6

```typescript { .api }

7

abstract class Output<T> {

8

apply<U>(func: (t: T) => Input<U>): Output<U>;

9

readonly isKnown: Promise<boolean>;

10

readonly isSecret: Promise<boolean>;

11

}

12

13

interface OutputInstance<T> extends Output<T> {

14

__pulumiOutput: true;

15

}

16

17

type Input<T> = T | Promise<T> | OutputInstance<T>;

18

type Inputs = Record<string, Input<any>>;

19

20

type Unwrap<T> = T extends OutputInstance<infer U> ? U :

21

T extends Promise<infer U> ? U : T;

22

23

type UnwrappedObject<T> = {

24

[K in keyof T]: Unwrap<T[K]>;

25

};

26

27

type Lifted<T> = {

28

[K in keyof T]: Output<T[K]>;

29

};

30

```

31

32

## Core Output Functions

33

34

```typescript { .api }

35

function output<T>(val: Input<T>): Output<Unwrap<T>>;

36

function secret<T>(val: Input<T>): Output<Unwrap<T>>;

37

function unsecret<T>(val: Input<T>): Output<Unwrap<T>>;

38

function isSecret<T>(val: Output<T>): Promise<boolean>;

39

40

function all<T>(values: T): Output<UnwrappedObject<T>>;

41

function concat(...params: Input<any>[]): Output<string>;

42

function interpolate(literals: TemplateStringsArray, ...placeholders: Input<any>[]): Output<string>;

43

44

function jsonStringify(val: Input<any>, replacer?: any, space?: Input<string | number>): Output<string>;

45

function jsonParse<T>(text: Input<string>, reviver?: any): Output<T>;

46

```

47

48

## Utility Functions

49

50

```typescript { .api }

51

function deferredOutput<T>(): { output: Output<T>; setter: (value: Input<T>) => void };

52

function getAllResources<T>(op: Output<T>): Resource[];

53

function isSecretOutput<T>(o: any): o is Output<T>;

54

function isUnknown(val: any): boolean;

55

function containsUnknowns(value: any): boolean;

56

```

57

58

## Error Classes

59

60

```typescript { .api }

61

class OutputToStringError extends Error {

62

constructor(message: string);

63

}

64

65

class Unknown {

66

readonly isKnown: false;

67

readonly isSecret: false;

68

}

69

```

70

71

## Usage Examples

72

73

### Basic Output Creation

74

75

```typescript

76

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

77

78

// Create output from values

79

const simpleOutput = pulumi.output("hello");

80

const promiseOutput = pulumi.output(Promise.resolve(42));

81

82

// Create secret outputs

83

const secretOutput = pulumi.secret("my-secret-value");

84

const secretFromConfig = new pulumi.Config().requireSecret("apiKey");

85

```

86

87

### Output Transformation

88

89

```typescript

90

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

91

92

const bucket = new aws.s3.Bucket("my-bucket");

93

94

// Transform a single output

95

const bucketUrl = bucket.id.apply(id => `https://${id}.s3.amazonaws.com`);

96

97

// Chain transformations

98

const processedName = bucket.id

99

.apply(id => id.toLowerCase())

100

.apply(id => id.replace(/-/g, "_"));

101

102

// Handle async transformations

103

const bucketSize = bucket.id.apply(async (id) => {

104

const response = await getBucketSize(id);

105

return response.size;

106

});

107

```

108

109

### Combining Multiple Outputs

110

111

```typescript

112

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

113

114

const bucket = new aws.s3.Bucket("my-bucket");

115

const distribution = new aws.cloudfront.Distribution("cdn", {

116

// ... config

117

});

118

119

// Combine multiple outputs into object

120

const combined = pulumi.all({

121

bucketName: bucket.id,

122

distributionId: distribution.id,

123

region: aws.getRegion().then(r => r.name),

124

}).apply(({ bucketName, distributionId, region }) => ({

125

url: `https://${distributionId}.cloudfront.net`,

126

bucket: bucketName,

127

region: region,

128

}));

129

130

// Combine into array

131

const urls = pulumi.all([

132

bucket.websiteEndpoint,

133

distribution.domainName,

134

]).apply(([bucketUrl, cdnUrl]) => ({

135

direct: `http://${bucketUrl}`,

136

cdn: `https://${cdnUrl}`,

137

}));

138

```

139

140

### String Interpolation

141

142

```typescript

143

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

144

145

const bucket = new aws.s3.Bucket("my-bucket");

146

const region = aws.getRegion();

147

148

// Template string interpolation

149

const bucketUrl = pulumi.interpolate`https://${bucket.id}.s3.${region.name}.amazonaws.com`;

150

151

// Complex interpolation

152

const configHtml = pulumi.interpolate`

153

<configuration>

154

<bucket>${bucket.id}</bucket>

155

<region>${region.name}</region>

156

<timestamp>${Date.now()}</timestamp>

157

</configuration>`;

158

```

159

160

### Concatenation

161

162

```typescript

163

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

164

165

const prefix = pulumi.output("prod");

166

const suffix = pulumi.output("db");

167

168

// Simple concatenation

169

const resourceName = pulumi.concat(prefix, "-", suffix);

170

171

// With multiple inputs

172

const fullPath = pulumi.concat(

173

"/api/v1/",

174

prefix,

175

"/",

176

suffix,

177

"/config"

178

);

179

```

180

181

### JSON Operations

182

183

```typescript

184

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

185

186

const config = pulumi.all({

187

database: {

188

host: "localhost",

189

port: 5432,

190

},

191

cache: {

192

host: "redis.example.com",

193

port: 6379,

194

},

195

});

196

197

// Convert to JSON string

198

const configJson = pulumi.jsonStringify(config, null, 2);

199

200

// Parse JSON string

201

const jsonString = pulumi.output('{"key": "value", "number": 42}');

202

const parsed = pulumi.jsonParse<{key: string; number: number}>(jsonString);

203

```

204

205

### Secret Handling

206

207

```typescript

208

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

209

210

const config = new pulumi.Config();

211

const dbPassword = config.requireSecret("dbPassword");

212

213

// Check if output is secret

214

const isSecretCheck = pulumi.isSecret(dbPassword); // Promise<boolean>

215

216

// Combine secret with non-secret (result is secret)

217

const connectionString = pulumi.interpolate`postgresql://user:${dbPassword}@localhost:5432/mydb`;

218

219

// Remove secret marking (use carefully!)

220

const plainPassword = pulumi.unsecret(dbPassword);

221

```

222

223

### Deferred Outputs

224

225

```typescript

226

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

227

228

// Create deferred output for complex initialization

229

const { output: deferredValue, setter: setValue } = pulumi.deferredOutput<string>();

230

231

// Set value later (perhaps after async operation)

232

async function initializeValue() {

233

const result = await someAsyncOperation();

234

setValue(result);

235

}

236

237

initializeValue();

238

239

// Use the deferred output

240

export const finalValue = deferredValue;

241

```

242

243

### Working with Unknown Values

244

245

```typescript

246

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

247

248

// During preview, some values are unknown

249

const bucket = new aws.s3.Bucket("my-bucket");

250

251

bucket.id.apply(id => {

252

if (pulumi.isUnknown(id)) {

253

console.log("Bucket ID is unknown during preview");

254

return "preview-placeholder";

255

}

256

return `Bucket ID: ${id}`;

257

});

258

259

// Check for unknowns in complex objects

260

const configObject = {

261

bucketId: bucket.id,

262

region: "us-east-1"

263

};

264

265

if (pulumi.containsUnknowns(configObject)) {

266

console.log("Config contains unknown values");

267

}

268

```

269

270

### Resource Dependencies

271

272

```typescript

273

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

274

275

const bucket = new aws.s3.Bucket("my-bucket");

276

277

// Get all resources that an output depends on

278

const dependencies = pulumi.getAllResources(bucket.id);

279

console.log(`Bucket ID depends on ${dependencies.length} resources`);

280

281

// Outputs automatically track dependencies

282

const bucketPolicy = new aws.s3.BucketPolicy("policy", {

283

bucket: bucket.id, // This creates a dependency

284

policy: bucket.arn.apply(arn => JSON.stringify({

285

Version: "2012-10-17",

286

Statement: [{

287

Effect: "Allow",

288

Principal: "*",

289

Action: "s3:GetObject",

290

Resource: `${arn}/*`

291

}]

292

}))

293

});

294

```

295

296

## Best Practices

297

298

- Use `apply()` for transforming single outputs

299

- Use `all()` for combining multiple outputs

300

- Use `interpolate` for string templates with outputs

301

- Mark sensitive data as secrets with `secret()`

302

- Handle unknown values gracefully in preview mode

303

- Avoid blocking operations in output transformations

304

- Chain transformations instead of nesting `apply()` calls

305

- Use TypeScript generics to maintain type safety through transformations