Parsers API#
Chef artifact parsing modules for recipes, templates, resources, attributes, and more.
Overview#
The souschef.parsers package contains specialized parsers for different Chef artifact types. Each parser extracts structured data from Ruby-based Chef code.
Parser Modules#
The following parsers are available:
- Recipe Parser (
souschef.parsers.recipe) - Parse Chef recipes - Template Parser (
souschef.parsers.template) - Extract ERB template variables - Resource Parser (
souschef.parsers.resource) - Parse custom resources - Attributes Parser (
souschef.parsers.attributes) - Parse attribute files - Metadata Parser (
souschef.parsers.metadata) - Parse cookbook metadata - InSpec Parser (
souschef.parsers.inspec) - Parse InSpec profiles - Habitat Parser (
souschef.parsers.habitat) - Parse Habitat plans - Ansible Inventory Parser (
souschef.parsers.ansible_inventory) - Parse Ansible inventory files and environments (NEW)
For usage examples and patterns, see the Examples Guide.
Common Parsing Patterns#
Ruby AST Parsing#
All parsers use regular expressions and Ruby syntax analysis:
import re
from pathlib import Path
class RecipeParser:
"""Parse Chef recipes."""
RESOURCE_PATTERN = re.compile(
r'^\s*(\w+)\s+([\'\"]([^'\"]+)[\'\"]|[\w-]+)\s+do',
re.MULTILINE
)
def parse(self, content: str) -> dict:
"""Extract resources from recipe."""
resources = []
for match in self.RESOURCE_PATTERN.finditer(content):
resource_type = match.group(1)
resource_name = match.group(3) or match.group(2)
resources.append({
'type': resource_type,
'name': resource_name
})
return {'resources': resources}
Error Handling#
def parse_file(filepath: str) -> dict:
"""Parse file with error handling."""
try:
with open(filepath, 'r') as f:
content = f.read()
return parse(content)
except FileNotFoundError:
raise ValueError(f"File not found: {filepath}")
except UnicodeDecodeError:
raise ValueError(f"Invalid encoding in file: {filepath}")
except Exception as e:
raise ValueError(f"Parse error: {e}")
Usage Examples#
Recipe Parsing#
from souschef.parsers.recipe import parse_recipe_file
# Parse a recipe
result = parse_recipe_file('recipes/default.rb')
# Access parsed data
for resource in result['resources']:
print(f"{resource['type']}: {resource['name']}")
Template Variable Extraction#
from souschef.parsers.template import parse_template_file
# Parse ERB template
result = parse_template_file('templates/config.erb')
# List all variables
for var in result['variables']:
print(f"Variable: {var}")
Attribute Parsing#
from souschef.parsers.attributes import parse_attributes_file
# Parse attributes
result = parse_attributes_file('attributes/default.rb')
# Access attributes
for attr in result['attributes']:
print(f"{attr['precedence']}['{attr['key']}']
= {attr['value']}")
Parser Performance#
Optimization Tips#
- Compile Patterns Once: Compile regex patterns at module level
- Stream Large Files: Use iterators for large files
- Cache Results: Cache parsed results when processing multiple times
- Parallel Processing: Use multiprocessing for batch operations
from concurrent.futures import ProcessPoolExecutor
from pathlib import Path
def parse_cookbook_parallel(cookbook_path: str) -> dict:
"""Parse all recipes in parallel."""
recipes = list(Path(cookbook_path).glob('recipes/*.rb'))
with ProcessPoolExecutor() as executor:
results = executor.map(parse_recipe_file, recipes)
return {'recipes': list(results)}
Testing Parsers#
See test suite for parser testing examples:
- Unit tests: tests/unit/test_server.py
- Integration tests: tests/integration/test_integration.py
- Property-based tests: tests/unit/test_property_based.py
See Also#
- Server API - MCP server using parsers
- Converters API - Convert parsed data
- Core Utilities - Shared utilities
- Examples - Real-world parsing examples