or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aws-resources.mdconstants.mdhelper-utilities.mdindex.mdintrinsic-functions.mdopenstack-support.mdparameters-outputs.mdtags-metadata.mdtemplate-management.mdvalidation.md

validation.mddocs/

0

# Validation

1

2

Comprehensive validation system with built-in validators for AWS-specific constraints, data types, and custom validation functions to ensure CloudFormation template correctness.

3

4

## Capabilities

5

6

### Core Validators

7

8

Basic data type and format validators for common CloudFormation parameter types.

9

10

```python { .api }

11

def boolean(x) -> bool:

12

"""

13

Convert value to boolean.

14

15

Args:

16

x: Value to convert (accepts various truthy/falsy formats)

17

18

Returns:

19

bool: Boolean value

20

"""

21

22

def integer(x) -> int:

23

"""

24

Validate and convert to integer.

25

26

Args:

27

x: Value to validate

28

29

Returns:

30

int: Integer value

31

32

Raises:

33

ValueError: If value cannot be converted to integer

34

"""

35

36

def positive_integer(x) -> int:

37

"""

38

Validate positive integer (>= 0).

39

40

Args:

41

x: Value to validate

42

43

Returns:

44

int: Positive integer value

45

46

Raises:

47

ValueError: If value is not a positive integer

48

"""

49

50

def integer_range(minimum: int, maximum: int) -> Callable:

51

"""

52

Create validator for integer within specified range.

53

54

Args:

55

minimum: Minimum allowed value (inclusive)

56

maximum: Maximum allowed value (inclusive)

57

58

Returns:

59

Callable: Validator function

60

"""

61

62

def double(x) -> float:

63

"""

64

Validate and convert to floating point number.

65

66

Args:

67

x: Value to validate

68

69

Returns:

70

float: Float value

71

72

Raises:

73

ValueError: If value cannot be converted to float

74

"""

75

76

def network_port(x) -> int:

77

"""

78

Validate network port number (0-65535).

79

80

Args:

81

x: Port number to validate

82

83

Returns:

84

int: Valid port number

85

86

Raises:

87

ValueError: If port is outside valid range

88

"""

89

```

90

91

### AWS-Specific Validators

92

93

Validators for AWS resource naming and format requirements.

94

95

```python { .api }

96

def s3_bucket_name(b) -> str:

97

"""

98

Validate S3 bucket name format.

99

100

Args:

101

b: Bucket name to validate

102

103

Returns:

104

str: Valid bucket name

105

106

Raises:

107

ValueError: If bucket name doesn't meet S3 requirements

108

"""

109

110

def elb_name(b) -> str:

111

"""

112

Validate Elastic Load Balancer name format.

113

114

Args:

115

b: ELB name to validate

116

117

Returns:

118

str: Valid ELB name

119

120

Raises:

121

ValueError: If name doesn't meet ELB requirements

122

"""

123

124

def encoding(encoding) -> str:

125

"""

126

Validate encoding type.

127

128

Args:

129

encoding: Encoding name to validate

130

131

Returns:

132

str: Valid encoding name

133

134

Raises:

135

ValueError: If encoding is not supported

136

"""

137

138

def json_checker(data) -> dict:

139

"""

140

Validate JSON structure.

141

142

Args:

143

data: Data to validate as JSON

144

145

Returns:

146

dict: Validated JSON data

147

148

Raises:

149

ValueError: If data is not valid JSON

150

"""

151

```

152

153

### Constraint Validators

154

155

Validators for enforcing property constraints and dependencies.

156

157

```python { .api }

158

def one_of(class_name: str, properties: dict, property: str, conditionals: list) -> None:

159

"""

160

Validate that property value is from allowed list.

161

162

Args:

163

class_name: Class name for error messages

164

properties: Properties dictionary

165

property: Property name to validate

166

conditionals: List of allowed values

167

168

Raises:

169

ValueError: If property value not in allowed list

170

"""

171

172

def mutually_exclusive(class_name: str, properties: dict, conditionals: list) -> None:

173

"""

174

Validate that only one of the specified properties is set.

175

176

Args:

177

class_name: Class name for error messages

178

properties: Properties dictionary

179

conditionals: List of mutually exclusive property names

180

181

Raises:

182

ValueError: If multiple exclusive properties are set

183

"""

184

185

def exactly_one(class_name: str, properties: dict, conditionals: list) -> None:

186

"""

187

Validate that exactly one of the specified properties is set.

188

189

Args:

190

class_name: Class name for error messages

191

properties: Properties dictionary

192

conditionals: List of property names (exactly one required)

193

194

Raises:

195

ValueError: If zero or multiple properties are set

196

"""

197

198

def check_required(class_name: str, properties: dict, conditionals: list) -> None:

199

"""

200

Validate that required properties are present.

201

202

Args:

203

class_name: Class name for error messages

204

properties: Properties dictionary

205

conditionals: List of required property names

206

207

Raises:

208

ValueError: If required properties are missing

209

"""

210

```

211

212

### Custom Validation Functions

213

214

Examples of creating custom validators for specific use cases.

215

216

```python { .api }

217

def validate_cidr_block(cidr: str) -> str:

218

"""

219

Custom validator for CIDR blocks.

220

221

Args:

222

cidr: CIDR block string

223

224

Returns:

225

str: Valid CIDR block

226

227

Raises:

228

ValueError: If CIDR format is invalid

229

"""

230

231

def validate_email(email: str) -> str:

232

"""

233

Custom validator for email addresses.

234

235

Args:

236

email: Email address string

237

238

Returns:

239

str: Valid email address

240

241

Raises:

242

ValueError: If email format is invalid

243

"""

244

245

def validate_tags(tags: dict) -> dict:

246

"""

247

Custom validator for tag dictionaries.

248

249

Args:

250

tags: Dictionary of tags

251

252

Returns:

253

dict: Valid tags dictionary

254

255

Raises:

256

ValueError: If tags format is invalid

257

"""

258

```

259

260

## Usage Examples

261

262

### Basic Type Validation

263

264

```python

265

from troposphere import Parameter

266

from troposphere.validators import positive_integer, network_port, boolean

267

268

# Parameter with positive integer validation

269

memory_size = Parameter(

270

"MemorySize",

271

Type="Number",

272

Default=128,

273

Description="Lambda function memory size in MB",

274

props={

275

"MemorySize": (positive_integer, True)

276

}

277

)

278

279

# Parameter with port validation

280

app_port = Parameter(

281

"ApplicationPort",

282

Type="Number",

283

Default=8080,

284

Description="Application port number",

285

props={

286

"ApplicationPort": (network_port, True)

287

}

288

)

289

290

# Boolean parameter with validation

291

enable_monitoring = Parameter(

292

"EnableMonitoring",

293

Type="String",

294

Default="true",

295

AllowedValues=["true", "false"],

296

Description="Enable CloudWatch monitoring",

297

props={

298

"EnableMonitoring": (boolean, False)

299

}

300

)

301

```

302

303

### AWS Resource Validation

304

305

```python

306

from troposphere.validators import s3_bucket_name, elb_name

307

from troposphere import Parameter

308

309

# S3 bucket name validation

310

bucket_name = Parameter(

311

"BucketName",

312

Type="String",

313

Description="S3 bucket name",

314

props={

315

"BucketName": (s3_bucket_name, True)

316

}

317

)

318

319

# ELB name validation

320

load_balancer_name = Parameter(

321

"LoadBalancerName",

322

Type="String",

323

Description="Load balancer name",

324

props={

325

"LoadBalancerName": (elb_name, True)

326

}

327

)

328

```

329

330

### Range Validation

331

332

```python

333

from troposphere.validators import integer_range

334

from troposphere import Parameter

335

336

# Create range validator

337

port_range_validator = integer_range(1024, 65535)

338

339

# Parameter with range validation

340

app_port = Parameter(

341

"ApplicationPort",

342

Type="Number",

343

Default=8080,

344

Description="Application port (1024-65535)",

345

props={

346

"ApplicationPort": (port_range_validator, True)

347

}

348

)

349

350

# Database storage size validation

351

storage_range_validator = integer_range(20, 1000)

352

353

db_storage = Parameter(

354

"DBStorageSize",

355

Type="Number",

356

Default=100,

357

Description="Database storage size in GB (20-1000)",

358

props={

359

"DBStorageSize": (storage_range_validator, True)

360

}

361

)

362

```

363

364

### Constraint Validation in Resources

365

366

```python

367

from troposphere import AWSProperty

368

from troposphere.validators import mutually_exclusive, exactly_one

369

370

class CustomProperty(AWSProperty):

371

props = {

372

"SourceType": (str, False),

373

"SourceValue": (str, False),

374

"SourceArn": (str, False),

375

"SourceAccount": (str, False)

376

}

377

378

def validate(self):

379

# Exactly one source must be specified

380

exactly_one(

381

self.__class__.__name__,

382

self.properties,

383

["SourceValue", "SourceArn", "SourceAccount"]

384

)

385

386

# Source type and value are mutually exclusive with ARN

387

mutually_exclusive(

388

self.__class__.__name__,

389

self.properties,

390

[["SourceType", "SourceValue"], ["SourceArn"]]

391

)

392

```

393

394

### Custom Validators

395

396

```python

397

import re

398

import ipaddress

399

from troposphere import Parameter

400

from troposphere.validators import one_of

401

402

def validate_cidr_block(cidr):

403

"""Validate CIDR block format."""

404

try:

405

ipaddress.IPv4Network(cidr, strict=False)

406

return cidr

407

except ValueError:

408

raise ValueError(f"Invalid CIDR block: {cidr}")

409

410

def validate_email(email):

411

"""Validate email address format."""

412

pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'

413

if not re.match(pattern, email):

414

raise ValueError(f"Invalid email address: {email}")

415

return email

416

417

def validate_instance_family(instance_type):

418

"""Validate instance type belongs to allowed families."""

419

allowed_families = ['t2', 't3', 'm5', 'c5', 'r5']

420

family = instance_type.split('.')[0]

421

if family not in allowed_families:

422

raise ValueError(f"Instance family {family} not allowed")

423

return instance_type

424

425

# Use custom validators in parameters

426

vpc_cidr = Parameter(

427

"VpcCidr",

428

Type="String",

429

Default="10.0.0.0/16",

430

Description="VPC CIDR block",

431

props={

432

"VpcCidr": (validate_cidr_block, True)

433

}

434

)

435

436

notification_email = Parameter(

437

"NotificationEmail",

438

Type="String",

439

Description="Email for notifications",

440

props={

441

"NotificationEmail": (validate_email, True)

442

}

443

)

444

445

instance_type = Parameter(

446

"InstanceType",

447

Type="String",

448

Default="t3.micro",

449

Description="EC2 instance type (restricted families)",

450

props={

451

"InstanceType": (validate_instance_family, True)

452

}

453

)

454

```

455

456

### Conditional Validation

457

458

```python

459

from troposphere import AWSObject

460

from troposphere.validators import check_required

461

462

class ConditionalResource(AWSObject):

463

props = {

464

"Type": (str, True),

465

"DatabaseConfig": (dict, False),

466

"CacheConfig": (dict, False),

467

"DatabaseEndpoint": (str, False),

468

"CacheEndpoint": (str, False)

469

}

470

471

def validate(self):

472

# Check conditional requirements based on type

473

if self.properties.get("Type") == "database":

474

check_required(

475

self.__class__.__name__,

476

self.properties,

477

["DatabaseConfig", "DatabaseEndpoint"]

478

)

479

elif self.properties.get("Type") == "cache":

480

check_required(

481

self.__class__.__name__,

482

self.properties,

483

["CacheConfig", "CacheEndpoint"]

484

)

485

```

486

487

### Validation with Error Handling

488

489

```python

490

from troposphere import Template, Parameter

491

from troposphere.validators import positive_integer

492

493

def safe_create_parameter(template, name, param_type, default_value, validator=None):

494

"""Safely create parameter with validation and error handling."""

495

try:

496

props = {}

497

if validator:

498

props[name] = (validator, True)

499

500

param = Parameter(

501

name,

502

Type=param_type,

503

Default=default_value,

504

props=props

505

)

506

507

return template.add_parameter(param)

508

509

except ValueError as e:

510

print(f"Validation error for parameter {name}: {e}")

511

raise

512

except Exception as e:

513

print(f"Error creating parameter {name}: {e}")

514

raise

515

516

# Usage

517

template = Template()

518

519

# This will succeed

520

memory_param = safe_create_parameter(

521

template, "MemorySize", "Number", 128, positive_integer

522

)

523

524

# This would fail validation

525

try:

526

invalid_param = safe_create_parameter(

527

template, "InvalidMemory", "Number", -1, positive_integer

528

)

529

except ValueError:

530

print("Caught validation error for negative memory size")

531

```