This guide shows you how to create data sources for your Pyvider provider. Data sources are read-only queries that fetch information from external systems.
🤖 AI-Generated Content
This documentation was generated with AI assistance and is still being audited. Some, or potentially a lot, of this information may be inaccurate. Learn more.
A data source in Terraform:
- Reads data from external systems (APIs, databases, files)
- Does not manage infrastructure (read-only)
- Returns computed values to be used by resources
frompyvider.data_sourcesimportregister_data_source,BaseDataSourcefrompyvider.schemaimports_data_source,a_str,a_num,a_bool,PvsSchemaimportattrs# Configuration (input from user)@attrs.defineclassFileInfoConfig:path:str# Data (output to user)@attrs.defineclassFileInfoData:id:strpath:strsize:intexists:boolcontent:str@register_data_source("file_info")classFileInfo(BaseDataSource):"""Reads information about a local file."""config_class=FileInfoConfigdata_class=FileInfoData@classmethoddefget_schema(cls)->PvsSchema:"""Define Terraform schema."""returns_data_source({# Input (from user)"path":a_str(required=True,description="File path to query"),# Outputs (computed by provider)"id":a_str(computed=True,description="File path as ID"),"size":a_num(computed=True,description="File size in bytes"),"exists":a_bool(computed=True,description="Whether file exists"),"content":a_str(computed=True,description="File content"),})asyncdefread(self,config:FileInfoConfig)->FileInfoData:"""Read file information."""frompathlibimportPathfile_path=Path(config.path)iffile_path.exists():content=file_path.read_text()size=file_path.stat().st_sizereturnFileInfoData(id=str(file_path.absolute()),path=str(file_path),size=size,exists=True,content=content,)else:returnFileInfoData(id=str(file_path.absolute()),path=str(file_path),size=0,exists=False,content="",)
@attrs.defineclassQueryConfig:"""Input from user."""filter:strlimit:int=10@attrs.defineclassQueryData:"""Output to user."""id:strresults:list[str]count:int
asyncdefread(self,config:QueryConfig)->QueryData:"""Fetch data based on configuration."""# Query your API/databaseresults=awaitself.fetch_data(config.filter,config.limit)returnQueryData(id=generate_id(config),results=results,count=len(results),)
# Query file informationdata"local_file_info""readme"{path="../README.md"}# Use the data in a resourceresource"local_file""summary"{path="summary.txt"content=<<EOTREADME size: ${data.local_file_info.readme.size} bytesExists: ${data.local_file_info.readme.exists}EOT}# Query APIdata"mycloud_api_query""servers"{endpoint="/servers"filter="status=running"limit=50}output"server_count"{value=data.mycloud_api_query.servers.count}
asyncdefread(self,config:QueryConfig)->QueryData:"""Read with error handling."""try:results=awaitself.api.query(config.filter)returnQueryData(id=generate_id(config),results=results,found=True,error=None,)exceptAPIErrorase:# Return empty data on errorreturnQueryData(id=generate_id(config),results=[],found=False,error=str(e),)
asyncdefread(self,config:QueryConfig)->QueryData:"""Read with pagination."""all_results=[]page=1max_pages=config.limit//100+1asyncwithhttpx.AsyncClient()asclient:whilepage<=max_pages:response=awaitclient.get(config.endpoint,params={"page":page,"per_page":100})data=response.json()all_results.extend(data["items"])ifnotdata.get("has_more"):breakpage+=1returnQueryData(id=generate_id(config),results=all_results[:config.limit],count=len(all_results[:config.limit]),total_available=len(all_results),)