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

resource-management.mddocs/

0

# Resource Management

1

2

Pulumi's resource management system provides the foundation for creating, managing, and organizing cloud infrastructure resources with automatic dependency tracking and lifecycle management.

3

4

## Core Resource Classes

5

6

```typescript { .api }

7

abstract class Resource {

8

readonly urn: Output<string>;

9

readonly __pulumiResource: boolean;

10

11

protected constructor(type: string, name: string, opts?: ResourceOptions);

12

}

13

14

class CustomResource extends Resource {

15

readonly id: Output<ID>;

16

readonly __pulumiCustomResource: boolean;

17

18

protected constructor(type: string, name: string, props?: any, opts?: CustomResourceOptions);

19

}

20

21

class ProviderResource extends CustomResource {

22

readonly pkg: string;

23

readonly __pulumiProviderResource: boolean;

24

25

protected constructor(pkg: string, name: string, props?: any, opts?: CustomResourceOptions);

26

}

27

28

class ComponentResource<TData = any> extends Resource {

29

readonly __pulumiComponentResource: boolean;

30

31

protected constructor(type: string, name: string, opts?: ComponentResourceOptions);

32

33

registerOutputs(outputs?: Inputs | Promise<Inputs> | Output<Inputs>): void;

34

}

35

```

36

37

## Resource Options

38

39

```typescript { .api }

40

interface ResourceOptions {

41

// Dependency management

42

dependsOn?: Input<Input<Resource>[]> | Input<Resource>;

43

parent?: Resource;

44

45

// Lifecycle options

46

protect?: boolean;

47

ignoreChanges?: string[];

48

deleteBeforeReplace?: boolean;

49

replaceOnChanges?: string[];

50

retainOnDelete?: boolean;

51

deletedWith?: Resource;

52

53

// Provider options

54

provider?: ProviderResource;

55

providers?: Record<string, ProviderResource>;

56

version?: string;

57

pluginDownloadURL?: string;

58

59

// Aliasing and transformation

60

aliases?: Input<Alias[]>;

61

customTimeouts?: CustomTimeouts;

62

transformations?: ResourceTransformation[];

63

transforms?: ResourceTransform[];

64

hooks?: ResourceHook[];

65

}

66

67

interface CustomResourceOptions extends ResourceOptions {

68

id?: Input<ID>;

69

import?: Input<string>;

70

importId?: Input<ID>;

71

}

72

73

interface ComponentResourceOptions extends ResourceOptions {

74

// ComponentResource-specific options

75

}

76

```

77

78

## Resource Lifecycle Types

79

80

```typescript { .api }

81

interface Alias {

82

name?: Input<string>;

83

type?: Input<string>;

84

parent?: Input<Resource>;

85

stack?: Input<string>;

86

project?: Input<string>;

87

}

88

89

interface CustomTimeouts {

90

create?: Input<string>;

91

update?: Input<string>;

92

delete?: Input<string>;

93

}

94

95

type ID = string;

96

type URN = string;

97

```

98

99

## Transformation System

100

101

```typescript { .api }

102

type ResourceTransform = (args: ResourceTransformArgs) => Promise<ResourceTransformResult | undefined> | ResourceTransformResult | undefined;

103

104

interface ResourceTransformArgs {

105

type: string;

106

name: string;

107

props: Inputs;

108

opts: ResourceOptions;

109

}

110

111

interface ResourceTransformResult {

112

props?: Inputs;

113

opts?: ResourceOptions;

114

}

115

116

// Legacy transformation system (deprecated)

117

type ResourceTransformation = (args: ResourceTransformationArgs) => Promise<ResourceTransformationResult | undefined> | ResourceTransformationResult | undefined;

118

```

119

120

## Hook System

121

122

```typescript { .api }

123

class ResourceHook {

124

constructor(options: ResourceHookOptions);

125

}

126

127

interface ResourceHookOptions {

128

before?: ResourceHookFunction;

129

after?: ResourceHookFunction;

130

}

131

132

type ResourceHookFunction = (args: ResourceHookArgs) => Promise<void> | void;

133

134

interface ResourceHookArgs {

135

type: string;

136

name: string;

137

props: Inputs;

138

opts: ResourceOptions;

139

resource: Resource;

140

}

141

```

142

143

## Utility Functions

144

145

```typescript { .api }

146

function createUrn(name: Input<string>, type: Input<string>, parent?: Resource, project?: string, stack?: string): Output<string>;

147

function allAliases(name: string, aliases: Input<Alias[]> | undefined, parent: Resource | undefined): Output<string>[];

148

function mergeOptions(opts1?: ResourceOptions, opts2?: ResourceOptions): ResourceOptions;

149

function parseResourceReference(ref: string): { urn: string; id?: string; packageVersion?: string };

150

function pkgFromType(type: string): string;

151

function resourceType(res: Resource): string;

152

function resourceName(res: Resource): string;

153

```

154

155

## Usage Examples

156

157

### Basic Resource Creation

158

159

```typescript

160

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

161

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

162

163

// Simple resource creation

164

const bucket = new aws.s3.Bucket("my-bucket", {

165

acl: "private",

166

versioning: {

167

enabled: true,

168

},

169

});

170

171

// Resource with explicit dependencies

172

const role = new aws.iam.Role("lambda-role", {

173

assumeRolePolicy: JSON.stringify({

174

Version: "2012-10-17",

175

Statement: [{

176

Effect: "Allow",

177

Principal: { Service: "lambda.amazonaws.com" },

178

Action: "sts:AssumeRole",

179

}],

180

}),

181

});

182

183

const lambda = new aws.lambda.Function("my-lambda", {

184

code: new pulumi.asset.AssetArchive({

185

".": new pulumi.asset.FileArchive("./lambda"),

186

}),

187

role: role.arn, // Automatic dependency

188

handler: "index.handler",

189

runtime: "nodejs18.x",

190

}, {

191

dependsOn: [role], // Explicit dependency

192

});

193

```

194

195

### Resource Options

196

197

```typescript

198

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

199

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

200

201

// Resource with comprehensive options

202

const database = new aws.rds.Instance("prod-db", {

203

engine: "postgres",

204

instanceClass: "db.t3.micro",

205

allocatedStorage: 20,

206

dbName: "myapp",

207

username: "admin",

208

password: new pulumi.Config().requireSecret("dbPassword"),

209

}, {

210

// Lifecycle protection

211

protect: true,

212

213

// Ignore changes to specific properties

214

ignoreChanges: ["password"],

215

216

// Custom timeout

217

customTimeouts: {

218

create: "30m",

219

update: "20m",

220

delete: "10m",

221

},

222

223

// Replace on specific property changes

224

replaceOnChanges: ["engine", "instanceClass"],

225

226

// Retain on delete

227

retainOnDelete: true,

228

});

229

```

230

231

### Component Resources

232

233

```typescript

234

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

235

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

236

237

interface WebsiteArgs {

238

domain: string;

239

indexContent: string;

240

}

241

242

class Website extends pulumi.ComponentResource {

243

public readonly bucketName: pulumi.Output<string>;

244

public readonly websiteUrl: pulumi.Output<string>;

245

246

constructor(name: string, args: WebsiteArgs, opts?: pulumi.ComponentResourceOptions) {

247

super("custom:Website", name, {}, opts);

248

249

// Create child resources

250

const bucket = new aws.s3.Bucket(`${name}-bucket`, {

251

website: {

252

indexDocument: "index.html",

253

},

254

}, { parent: this });

255

256

const indexObject = new aws.s3.BucketObject(`${name}-index`, {

257

bucket: bucket.id,

258

key: "index.html",

259

content: args.indexContent,

260

contentType: "text/html",

261

}, { parent: this });

262

263

// Set outputs

264

this.bucketName = bucket.id;

265

this.websiteUrl = bucket.websiteEndpoint;

266

267

// Register outputs for the component

268

this.registerOutputs({

269

bucketName: this.bucketName,

270

websiteUrl: this.websiteUrl,

271

});

272

}

273

}

274

275

// Use the component

276

const website = new Website("my-website", {

277

domain: "example.com",

278

indexContent: "<h1>Hello World</h1>",

279

});

280

```

281

282

### Resource Transformations

283

284

```typescript

285

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

286

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

287

288

// Global transformation to add common tags

289

const addCommonTags: pulumi.ResourceTransform = (args) => {

290

if (args.type.startsWith("aws:")) {

291

return {

292

props: {

293

...args.props,

294

tags: {

295

...args.props.tags,

296

Environment: "production",

297

ManagedBy: "pulumi",

298

Project: pulumi.getProject(),

299

},

300

},

301

opts: args.opts,

302

};

303

}

304

return undefined;

305

};

306

307

// Apply transformation to specific resources

308

const bucket = new aws.s3.Bucket("my-bucket", {

309

acl: "private",

310

}, {

311

transforms: [addCommonTags],

312

});

313

314

// Or apply globally via stack options

315

const stack = new pulumi.ComponentResource("MyStack", "my-stack", {}, {

316

transforms: [addCommonTags],

317

});

318

```

319

320

### Resource Hooks

321

322

```typescript

323

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

324

325

// Create hooks for monitoring resource creation

326

const loggingHook = new pulumi.ResourceHook({

327

before: (args) => {

328

console.log(`Creating resource: ${args.type}:${args.name}`);

329

},

330

after: (args) => {

331

console.log(`Created resource: ${args.type}:${args.name}`);

332

},

333

});

334

335

const bucket = new aws.s3.Bucket("my-bucket", {

336

acl: "private",

337

}, {

338

hooks: [loggingHook],

339

});

340

```

341

342

### Resource Aliases

343

344

```typescript

345

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

346

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

347

348

// Handle resource renames with aliases

349

const bucket = new aws.s3.Bucket("my-new-bucket", {

350

acl: "private",

351

}, {

352

aliases: [

353

{ name: "my-old-bucket" },

354

{ name: "my-very-old-bucket", type: "aws:s3/bucket:Bucket" },

355

],

356

});

357

```

358

359

### Resource Import

360

361

```typescript

362

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

363

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

364

365

// Import existing resource

366

const existingBucket = new aws.s3.Bucket("imported-bucket", {

367

// Properties must match existing resource

368

acl: "private",

369

versioning: {

370

enabled: false,

371

},

372

}, {

373

import: "existing-bucket-name",

374

});

375

```

376

377

### Advanced Dependency Management

378

379

```typescript

380

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

381

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

382

383

const vpc = new aws.ec2.Vpc("main-vpc", {

384

cidrBlock: "10.0.0.0/16",

385

});

386

387

const subnet = new aws.ec2.Subnet("main-subnet", {

388

vpcId: vpc.id,

389

cidrBlock: "10.0.1.0/24",

390

});

391

392

const securityGroup = new aws.ec2.SecurityGroup("web-sg", {

393

vpcId: vpc.id,

394

ingress: [{

395

fromPort: 80,

396

toPort: 80,

397

protocol: "tcp",

398

cidrBlocks: ["0.0.0.0/0"],

399

}],

400

});

401

402

// Resource with multiple dependencies

403

const instance = new aws.ec2.Instance("web-server", {

404

ami: "ami-12345678",

405

instanceType: "t3.micro",

406

subnetId: subnet.id,

407

vpcSecurityGroupIds: [securityGroup.id],

408

}, {

409

// Explicit additional dependencies

410

dependsOn: [vpc], // Even though implicit via subnet

411

412

// Delete this resource with the VPC

413

deletedWith: vpc,

414

});

415

```

416

417

## Best Practices

418

419

- Use component resources to create reusable infrastructure patterns

420

- Leverage automatic dependency tracking through resource references

421

- Use explicit `dependsOn` only when implicit dependencies aren't sufficient

422

- Protect critical resources with the `protect` option

423

- Use aliases when renaming or restructuring resources

424

- Apply transformations for consistent resource configuration

425

- Use custom timeouts for long-running operations

426

- Consider `replaceOnChanges` for properties that require replacement

427

- Use `retainOnDelete` for resources that should persist after stack deletion