0
# Provisioners
1
2
Resource provisioning capabilities for executing scripts, transferring files, and performing custom actions during resource lifecycle events.
3
4
## Capabilities
5
6
### Provisioner Types
7
8
Terraform supports three main provisioner types for executing actions during resource creation and destruction.
9
10
```typescript { .api }
11
/**
12
* File provisioner for transferring files to resources
13
*/
14
interface FileProvisioner {
15
readonly type: "file";
16
readonly source: string;
17
readonly destination: string;
18
readonly connection?: SSHProvisionerConnection | WinrmProvisionerConnection;
19
}
20
21
/**
22
* Local execution provisioner for running commands locally
23
*/
24
interface LocalExecProvisioner {
25
readonly type: "local-exec";
26
readonly command: string;
27
readonly workingDir?: string;
28
readonly interpreter?: string[];
29
readonly environment?: {[key: string]: string};
30
readonly when?: "create" | "destroy";
31
}
32
33
/**
34
* Remote execution provisioner for running commands on resources
35
*/
36
interface RemoteExecProvisioner {
37
readonly type: "remote-exec";
38
readonly inline?: string[];
39
readonly script?: string;
40
readonly scripts?: string[];
41
readonly connection: SSHProvisionerConnection | WinrmProvisionerConnection;
42
readonly when?: "create" | "destroy";
43
}
44
```
45
46
**Usage Examples:**
47
48
```typescript
49
import { AwsInstance } from "cdktf";
50
51
// Instance with multiple provisioners
52
new AwsInstance(this, "web-server", {
53
ami: "ami-12345678",
54
instanceType: "t2.micro",
55
keyName: "my-key",
56
57
provisioners: [
58
// Upload configuration file
59
{
60
type: "file",
61
source: "./config/app.conf",
62
destination: "/tmp/app.conf",
63
connection: {
64
type: "ssh",
65
user: "ubuntu",
66
privateKey: "${file(var.private_key_path)}"
67
}
68
},
69
70
// Run setup script locally
71
{
72
type: "local-exec",
73
command: "echo 'Instance ${self.id} is being created'"
74
},
75
76
// Configure the server remotely
77
{
78
type: "remote-exec",
79
inline: [
80
"sudo apt-get update",
81
"sudo apt-get install -y nginx",
82
"sudo cp /tmp/app.conf /etc/nginx/sites-available/",
83
"sudo systemctl enable nginx",
84
"sudo systemctl start nginx"
85
],
86
connection: {
87
type: "ssh",
88
user: "ubuntu",
89
privateKey: "${file(var.private_key_path)}",
90
host: "${self.public_ip}"
91
}
92
}
93
]
94
});
95
```
96
97
### Connection Configuration
98
99
Provisioners require connection configurations to access remote resources.
100
101
```typescript { .api }
102
/**
103
* SSH connection configuration
104
*/
105
interface SSHProvisionerConnection {
106
readonly type: "ssh";
107
readonly user: string;
108
readonly password?: string;
109
readonly privateKey?: string;
110
readonly certificate?: string;
111
readonly host?: string;
112
readonly port?: number;
113
readonly timeout?: string;
114
readonly scriptPath?: string;
115
readonly bastionHost?: string;
116
readonly bastionHostKey?: string;
117
readonly bastionPort?: number;
118
readonly bastionUser?: string;
119
readonly bastionPassword?: string;
120
readonly bastionPrivateKey?: string;
121
readonly bastionCertificate?: string;
122
readonly agentIdentity?: string;
123
readonly agent?: boolean;
124
readonly hostKey?: string;
125
}
126
127
/**
128
* Windows Remote Management connection configuration
129
*/
130
interface WinrmProvisionerConnection {
131
readonly type: "winrm";
132
readonly user: string;
133
readonly password: string;
134
readonly host?: string;
135
readonly port?: number;
136
readonly timeout?: string;
137
readonly https?: boolean;
138
readonly insecure?: boolean;
139
readonly useNtlm?: boolean;
140
readonly cacert?: string;
141
readonly cert?: string;
142
readonly key?: string;
143
}
144
```
145
146
**Usage Examples:**
147
148
```typescript
149
// SSH with private key
150
const sshConnection: SSHProvisionerConnection = {
151
type: "ssh",
152
user: "ubuntu",
153
privateKey: "${file(var.private_key_path)}",
154
host: "${self.public_ip}",
155
timeout: "2m"
156
};
157
158
// SSH with bastion host
159
const bastionConnection: SSHProvisionerConnection = {
160
type: "ssh",
161
user: "ubuntu",
162
privateKey: "${file(var.private_key_path)}",
163
host: "${self.private_ip}",
164
bastionHost: "bastion.example.com",
165
bastionUser: "ubuntu",
166
bastionPrivateKey: "${file(var.bastion_key_path)}"
167
};
168
169
// WinRM connection
170
const winrmConnection: WinrmProvisionerConnection = {
171
type: "winrm",
172
user: "Administrator",
173
password: "${var.admin_password}",
174
host: "${self.public_ip}",
175
port: 5985,
176
timeout: "10m"
177
};
178
```
179
180
### TerraformSelf Class
181
182
Utility class for self-references within provisioners and resources.
183
184
```typescript { .api }
185
/**
186
* Self-reference utilities for provisioners
187
*/
188
class TerraformSelf {
189
/**
190
* Get string attribute from the current resource
191
* @param key - Attribute name
192
* @returns String value
193
*/
194
static getString(key: string): string;
195
196
/**
197
* Get number attribute from the current resource
198
* @param key - Attribute name
199
* @returns Number value
200
*/
201
static getNumber(key: string): number;
202
203
/**
204
* Get any attribute from the current resource
205
* @param key - Attribute name
206
* @returns Any value
207
*/
208
static getAny(key: string): any;
209
}
210
```
211
212
**Usage Examples:**
213
214
```typescript
215
import { TerraformSelf } from "cdktf";
216
217
new AwsInstance(this, "web", {
218
ami: "ami-12345678",
219
instanceType: "t2.micro",
220
221
provisioners: [
222
{
223
type: "local-exec",
224
command: `echo 'Instance IP: ${TerraformSelf.getString("public_ip")}'`
225
},
226
{
227
type: "remote-exec",
228
inline: [
229
`echo 'My ID is ${TerraformSelf.getString("id")}'`,
230
`echo 'My private IP is ${TerraformSelf.getString("private_ip")}'`
231
],
232
connection: {
233
type: "ssh",
234
user: "ubuntu",
235
privateKey: "${file(var.key_path)}",
236
host: TerraformSelf.getString("public_ip")
237
}
238
}
239
]
240
});
241
```
242
243
### Advanced Provisioner Patterns
244
245
#### Conditional Provisioning
246
247
```typescript
248
import { Fn } from "cdktf";
249
250
const enableMonitoring = new TerraformVariable(this, "enable_monitoring", {
251
type: "bool",
252
default: false
253
});
254
255
new AwsInstance(this, "app-server", {
256
ami: "ami-12345678",
257
instanceType: "t2.micro",
258
259
provisioners: [
260
// Always run basic setup
261
{
262
type: "remote-exec",
263
inline: [
264
"sudo apt-get update",
265
"sudo apt-get install -y nginx"
266
],
267
connection: sshConnection
268
},
269
270
// Conditionally install monitoring
271
...(enableMonitoring.booleanValue ? [{
272
type: "remote-exec",
273
inline: [
274
"curl -sSL https://agent.datadoghq.com/install.sh | bash",
275
"sudo systemctl enable datadog-agent",
276
"sudo systemctl start datadog-agent"
277
],
278
connection: sshConnection
279
}] : [])
280
]
281
});
282
```
283
284
#### Multi-Stage Provisioning
285
286
```typescript
287
new AwsInstance(this, "database-server", {
288
ami: "ami-12345678",
289
instanceType: "t3.large",
290
291
provisioners: [
292
// Stage 1: Upload files
293
{
294
type: "file",
295
source: "./scripts/setup-database.sh",
296
destination: "/tmp/setup-database.sh",
297
connection: sshConnection
298
},
299
{
300
type: "file",
301
source: "./config/database.conf",
302
destination: "/tmp/database.conf",
303
connection: sshConnection
304
},
305
306
// Stage 2: Setup system
307
{
308
type: "remote-exec",
309
inline: [
310
"chmod +x /tmp/setup-database.sh",
311
"sudo /tmp/setup-database.sh"
312
],
313
connection: sshConnection
314
},
315
316
// Stage 3: Configure application
317
{
318
type: "remote-exec",
319
script: "./scripts/configure-app.sh",
320
connection: sshConnection
321
},
322
323
// Stage 4: Local notification
324
{
325
type: "local-exec",
326
command: "curl -X POST -H 'Content-type: application/json' --data '{\"text\":\"Database server ${self.id} is ready\"}' ${var.slack_webhook_url}"
327
}
328
]
329
});
330
```
331
332
#### Destroy-Time Provisioning
333
334
```typescript
335
new AwsInstance(this, "app-server", {
336
ami: "ami-12345678",
337
instanceType: "t2.micro",
338
339
provisioners: [
340
// Creation-time provisioner
341
{
342
type: "remote-exec",
343
inline: [
344
"sudo systemctl start myapp"
345
],
346
connection: sshConnection
347
},
348
349
// Destroy-time provisioner for cleanup
350
{
351
type: "remote-exec",
352
when: "destroy",
353
inline: [
354
"sudo systemctl stop myapp",
355
"sudo rm -rf /var/lib/myapp/data",
356
"sudo userdel myapp"
357
],
358
connection: sshConnection
359
},
360
361
// Local cleanup
362
{
363
type: "local-exec",
364
when: "destroy",
365
command: "rm -f ./generated-config-${self.id}.json"
366
}
367
]
368
});
369
```
370
371
### Error Handling and Retries
372
373
```typescript
374
new AwsInstance(this, "web-server", {
375
ami: "ami-12345678",
376
instanceType: "t2.micro",
377
378
provisioners: [
379
{
380
type: "remote-exec",
381
inline: [
382
// Wait for cloud-init to complete
383
"while [ ! -f /var/lib/cloud/instance/boot-finished ]; do echo 'Waiting for cloud-init...'; sleep 2; done",
384
385
// Retry package installation
386
"for i in {1..5}; do sudo apt-get update && break || sleep 5; done",
387
"for i in {1..5}; do sudo apt-get install -y nginx && break || sleep 5; done",
388
389
// Verify installation
390
"systemctl is-active nginx || exit 1"
391
],
392
connection: {
393
type: "ssh",
394
user: "ubuntu",
395
privateKey: "${file(var.private_key_path)}",
396
host: "${self.public_ip}",
397
timeout: "5m"
398
}
399
}
400
]
401
});
402
```