or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aws-hooks.mdcli.mdcompilation-hooks.mdcore-objects.mdhelpers.mdindex.mdresource-collections.md

compilation-hooks.mddocs/

0

# Compilation and Hooks

1

2

System for compiling registered Terraform objects to JSON format and extending functionality through transformation hooks. This includes global object registry management, compilation control, and an extensible hook system for modifying objects during the compilation process.

3

4

## Capabilities

5

6

### Object Compilation

7

8

Functions for converting registered Terraform objects into Terraform JSON configuration format and managing the global object registry.

9

10

```python { .api }

11

def compile() -> dict:

12

"""

13

Compile all registered Terraform objects to dictionary format.

14

15

Returns:

16

dict - Complete Terraform configuration as Python dictionary

17

18

The compilation process:

19

1. Collects all registered TFObject instances

20

2. Applies transformation hooks for each object type

21

3. Organizes objects by Terraform type (resource, data, provider, etc.)

22

4. Generates properly formatted Terraform JSON

23

24

Example:

25

terraform_json = compile()

26

print(terraform_json) # Complete Terraform configuration

27

"""

28

29

def reset() -> None:

30

"""

31

Clear all registered objects from the global registry.

32

33

Use this function to start fresh configurations or between test runs.

34

After calling reset(), previously created objects will no longer be

35

included in compilation output.

36

37

Example:

38

# Create some resources

39

Resource('aws_instance', 'web')

40

compile() # Includes the instance

41

42

reset() # Clear registry

43

compile() # Empty configuration

44

"""

45

```

46

47

### Hook System

48

49

Extensible system for transforming Terraform objects during compilation, enabling custom modifications, validation, and schema transformations.

50

51

```python { .api }

52

class TFObject:

53

@classmethod

54

def add_hook(cls, object_type: str, hook_function: Callable[[dict], dict]) -> None:

55

"""

56

Add a transformation hook for objects of the specified type.

57

58

Parameters:

59

- object_type: str - Terraform object type to hook (e.g., 'resource', 'provider')

60

- hook_function: Callable - Function that transforms the complete output dictionary

61

62

Hook function signature:

63

def hook_function(output: dict) -> dict:

64

# output: Complete Terraform output dictionary for this object type

65

# Return: Modified output dictionary

66

67

Note: This is the low-level hook interface. For easier use with specific

68

resource types, use Resource.add_hook() or Provider.add_hook() instead.

69

70

Example:

71

def my_hook(output):

72

# Modify entire resource section

73

if 'resource' in output:

74

for resource_type in output['resource']:

75

for resource_name in output['resource'][resource_type]:

76

# Add common tags to all resources

77

output['resource'][resource_type][resource_name].setdefault('tags', {})

78

output['resource'][resource_type][resource_name]['tags']['ManagedBy'] = 'Terraformpy'

79

return output

80

81

TFObject.add_hook('resource', my_hook)

82

"""

83

84

# High-level hook interfaces for specific object types:

85

86

# For Resource and Data objects (TypedObject subclasses):

87

Resource.add_hook(resource_type: str, hook_function: Callable[[str, dict], dict]) -> None

88

Data.add_hook(data_type: str, hook_function: Callable[[str, dict], dict]) -> None

89

90

# For Provider, Variable, Output, Module objects (NamedObject subclasses):

91

Provider.add_hook(provider_name: str, hook_function: Callable[[dict], dict]) -> None

92

Variable.add_hook(variable_name: str, hook_function: Callable[[dict], dict]) -> None

93

Output.add_hook(output_name: str, hook_function: Callable[[dict], dict]) -> None

94

Module.add_hook(module_name: str, hook_function: Callable[[dict], dict]) -> None

95

96

@classmethod

97

def compile(cls) -> dict:

98

"""

99

Class method version of compile() function.

100

101

Returns:

102

dict - Complete Terraform configuration dictionary

103

104

This is equivalent to the standalone compile() function.

105

"""

106

107

@classmethod

108

def reset(cls) -> None:

109

"""

110

Class method version of reset() function.

111

112

Clears all registered objects from the global registry.

113

This is equivalent to the standalone reset() function.

114

"""

115

```

116

117

## Usage Examples

118

119

### Basic Compilation Workflow

120

121

```python

122

from terraformpy import Resource, Variable, Output, compile, reset

123

124

# Create Terraform objects

125

env = Variable('environment', default='dev')

126

web_server = Resource('aws_instance', 'web',

127

instance_type='t3.micro',

128

tags={'Environment': env.ref()}

129

)

130

Output('instance_id', value=web_server.id)

131

132

# Compile to JSON

133

terraform_config = compile()

134

print(terraform_config)

135

136

# Clear for next configuration

137

reset()

138

139

# Verify registry is empty

140

empty_config = compile()

141

print(empty_config) # Should be empty or minimal

142

```

143

144

### Hook-Based Transformations

145

146

```python

147

from terraformpy import Resource, TFObject

148

149

# Hook to add standard tags to all EC2 instances

150

def add_standard_tags(object_id, attrs):

151

"""Add standard tags to EC2 instances."""

152

attrs['tags'] = attrs.get('tags', {})

153

attrs['tags'].update({

154

'ManagedBy': 'Terraformpy',

155

'CreatedAt': '2023-01-01' # Could use datetime.now()

156

})

157

return attrs

158

159

# Hook to enforce naming convention

160

def enforce_naming_convention(object_id, attrs):

161

"""Ensure instance names follow convention."""

162

tags = attrs.get('tags', {})

163

if 'Name' in tags and not tags['Name'].startswith('app-'):

164

tags['Name'] = f"app-{tags['Name']}"

165

attrs['tags'] = tags

166

return attrs

167

168

# Register hooks

169

TFObject.add_hook('aws_instance', add_standard_tags)

170

TFObject.add_hook('aws_instance', enforce_naming_convention)

171

172

# Create resources - hooks will be applied automatically

173

web_server = Resource('aws_instance', 'web',

174

instance_type='t3.micro',

175

tags={'Name': 'webserver', 'Environment': 'prod'}

176

)

177

178

# Compile - hooks transform the resource

179

config = compile()

180

# The instance will have:

181

# - Name: 'app-webserver' (enforced naming)

182

# - ManagedBy: 'Terraformpy' (standard tag)

183

# - CreatedAt: '2023-01-01' (standard tag)

184

# - Environment: 'prod' (original tag preserved)

185

```

186

187

### AWS Security Group Hook Example

188

189

```python

190

from terraformpy import Resource

191

from terraformpy.hooks.aws import install_aws_security_group_attributes_as_blocks_hook

192

193

# Install the AWS security group hook

194

install_aws_security_group_attributes_as_blocks_hook()

195

196

# Create security group - hook will transform rule format

197

web_sg = Resource('aws_security_group', 'web',

198

name='web-sg',

199

description='Security group for web servers',

200

201

# These attributes will be transformed by the hook

202

ingress=[

203

{

204

'from_port': 80,

205

'to_port': 80,

206

'protocol': 'tcp',

207

'cidr_blocks': ['0.0.0.0/0']

208

},

209

{

210

'from_port': 443,

211

'to_port': 443,

212

'protocol': 'tcp',

213

'cidr_blocks': ['0.0.0.0/0']

214

}

215

]

216

)

217

218

# Compile - AWS hook transforms ingress rules to proper format

219

config = compile()

220

```

221

222

### Custom Validation Hook

223

224

```python

225

from terraformpy import Resource, TFObject

226

227

def validate_instance_type(object_id, attrs):

228

"""Validate EC2 instance types for cost control."""

229

allowed_types = ['t3.nano', 't3.micro', 't3.small']

230

instance_type = attrs.get('instance_type', '')

231

232

if instance_type not in allowed_types:

233

raise ValueError(f"Instance type {instance_type} not allowed for {object_id}. "

234

f"Allowed types: {allowed_types}")

235

236

return attrs

237

238

def add_cost_center(object_id, attrs):

239

"""Ensure all resources have cost center tag."""

240

attrs['tags'] = attrs.get('tags', {})

241

if 'CostCenter' not in attrs['tags']:

242

attrs['tags']['CostCenter'] = 'engineering'

243

244

return attrs

245

246

# Register validation and tagging hooks

247

TFObject.add_hook('aws_instance', validate_instance_type)

248

TFObject.add_hook('aws_instance', add_cost_center)

249

250

# This will pass validation

251

web_server = Resource('aws_instance', 'web',

252

instance_type='t3.micro',

253

ami='ami-12345678'

254

)

255

256

# This will raise ValueError during compilation

257

try:

258

expensive_server = Resource('aws_instance', 'expensive',

259

instance_type='c5.24xlarge', # Not in allowed list

260

ami='ami-12345678'

261

)

262

compile() # Validation hook will raise error here

263

except ValueError as e:

264

print(f"Validation failed: {e}")

265

```

266

267

### Hook for Resource Dependencies

268

269

```python

270

from terraformpy import Resource, TFObject

271

272

def add_dependency_tags(object_id, attrs):

273

"""Add dependency information to resources."""

274

# Extract resource type and name from object_id

275

# Format: "resource_type.resource_name"

276

resource_type, resource_name = object_id.split('.', 1)

277

278

attrs['tags'] = attrs.get('tags', {})

279

attrs['tags']['ResourceType'] = resource_type

280

attrs['tags']['ResourceName'] = resource_name

281

282

return attrs

283

284

# Hook to automatically add VPC tags to subnet resources

285

def add_vpc_context(object_id, attrs):

286

"""Add VPC context to subnet resources."""

287

if 'aws_subnet' in object_id:

288

attrs['tags'] = attrs.get('tags', {})

289

attrs['tags']['NetworkTier'] = 'private' if 'private' in object_id else 'public'

290

291

return attrs

292

293

# Register hooks for multiple resource types

294

for resource_type in ['aws_instance', 'aws_security_group', 'aws_subnet']:

295

TFObject.add_hook(resource_type, add_dependency_tags)

296

297

TFObject.add_hook('aws_subnet', add_vpc_context)

298

299

# Create resources

300

private_subnet = Resource('aws_subnet', 'private_web',

301

vpc_id='${aws_vpc.main.id}',

302

cidr_block='10.0.1.0/24'

303

)

304

305

web_server = Resource('aws_instance', 'web_server',

306

subnet_id=private_subnet.id,

307

instance_type='t3.micro'

308

)

309

310

# Compile with hooks applied

311

config = compile()

312

```

313

314

### Conditional Hook Application

315

316

```python

317

from terraformpy import Resource, Variable, TFObject

318

import os

319

320

def environment_specific_hook(object_id, attrs):

321

"""Apply different transformations based on environment."""

322

environment = os.getenv('ENVIRONMENT', 'dev')

323

324

attrs['tags'] = attrs.get('tags', {})

325

attrs['tags']['Environment'] = environment

326

327

if environment == 'production':

328

# Production-specific settings

329

attrs['tags']['Backup'] = 'daily'

330

attrs['tags']['Monitoring'] = 'enabled'

331

332

# Enable detailed monitoring for production instances

333

if 'aws_instance' in object_id:

334

attrs['monitoring'] = True

335

attrs['ebs_optimized'] = True

336

337

elif environment == 'development':

338

# Development-specific settings

339

attrs['tags']['Backup'] = 'none'

340

attrs['tags']['AutoShutdown'] = '6pm'

341

342

return attrs

343

344

# Register environment-aware hook

345

for resource_type in ['aws_instance', 'aws_rds_instance', 'aws_efs_file_system']:

346

TFObject.add_hook(resource_type, environment_specific_hook)

347

348

# Create resources - hooks will apply environment-specific settings

349

web_server = Resource('aws_instance', 'web',

350

instance_type='t3.micro',

351

ami='ami-12345678'

352

)

353

354

# Environment determines the final configuration

355

config = compile()

356

```

357

358

## AWS Specific Hooks

359

360

### Pre-built AWS Security Group Hook

361

362

```python

363

from terraformpy.hooks.aws import (

364

install_aws_security_group_attributes_as_blocks_hook,

365

fill_in_optional_aws_security_group_rules_attrs

366

)

367

368

# Install the built-in AWS security group transformation hook

369

install_aws_security_group_attributes_as_blocks_hook()

370

371

# The hook function can also be used directly

372

def custom_sg_hook(object_id, attrs):

373

"""Custom wrapper around AWS security group hook."""

374

# Apply the built-in transformation first

375

attrs = fill_in_optional_aws_security_group_rules_attrs(object_id, attrs)

376

377

# Add custom logic

378

attrs['tags'] = attrs.get('tags', {})

379

attrs['tags']['SecurityLevel'] = 'standard'

380

381

return attrs

382

383

# Register custom hook that includes built-in functionality

384

TFObject.add_hook('aws_security_group', custom_sg_hook)

385

```