This page documents the ephemeral resources API for creating short-lived, stateless resources in Terraform providers.
🤖 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.
Ephemeral resources are a special type of resource that manage temporary connections, sessions, or other short-lived infrastructure. Unlike regular resources, ephemeral resources:
Have a different lifecycle: open, renew, and close (each receives an EphemeralResourceContext)
Are not persisted in Terraform state
Are recreated on every Terraform run
Perfect for database connections, API sessions, temporary credentials, etc.
frompyvider.ephemeralsimportregister_ephemeral_resource@register_ephemeral_resource("database_session")classDatabaseSession:"""Manages a temporary database session."""pass
Parameters:
- name (str): The resource name as it appears in Terraform configurations
frompyvider.ephemeralsimportBaseEphemeralResourcefrompyvider.resources.private_stateimportPrivateStatefrompyvider.schemaimporta_str,a_numimportattrsclassMyEphemeral(BaseEphemeralResource):"""Base class for ephemeral resources."""@attrs.defineclassConfig:"""Configuration from Terraform."""host:str=a_str(required=True)port:int=a_num(default=5432)@attrs.defineclassResult:"""Data returned to Terraform callers."""session_id:str=a_str(computed=True)expires_at:str=a_str(computed=True)@attrs.defineclassSessionState(PrivateState):token:str=a_str(sensitive=True)
asyncdefopen(self,ctx:EphemeralResourceContext[Config,None])->tuple[Result,PrivateState,datetime]:""" Open a new ephemeral resource instance. Returns: (result, private_state, renew_at_utc) """session=awaitself.provider.create_session(host=ctx.config.host,port=ctx.config.port,)return(self.Result(session_id=session.id,expires_at=session.expires_at.isoformat()),self.PrivateState(token=session.token),session.expires_at,)
asyncdefclose(self,ctx:EphemeralResourceContext[None,PrivateState])->None:""" Close the ephemeral resource and clean up server-side state. """awaitself.provider.close_session(ctx.private_state.token)
frompyvider.ephemeralsimportregister_ephemeral_resource,BaseEphemeralResource,EphemeralResourceContextfrompyvider.resources.private_stateimportPrivateStatefrompyvider.schemaimporta_str,a_num,a_bool,a_listfromdatetimeimportdatetime,timedeltaimportattrsimportuuid@register_ephemeral_resource("api_token")classApiToken(BaseEphemeralResource):""" Manages temporary API tokens with automatic expiration. """@attrs.defineclassConfig:"""Token configuration."""scopes:list[str]=a_list(a_str(),required=True)ttl_seconds:int=a_num(default=3600)auto_renew:bool=a_bool(default=True)@attrs.defineclassResult:token:str=a_str(computed=True,sensitive=True)token_id:str=a_str(computed=True)expires_at:str=a_str(computed=True)scopes:list[str]=a_list(a_str(),computed=True)@attrs.defineclassTokenPrivateState(PrivateState):token:str=a_str(sensitive=True)asyncdefopen(self,ctx:EphemeralResourceContext[Config,None])->tuple[Result,PrivateState,datetime]:"""Generate a new API token."""response=awaitself.provider.api_client.create_token(scopes=ctx.config.scopes,ttl=ctx.config.ttl_seconds)expires_at=response.expires_atordatetime.utcnow()+timedelta(hours=1)return(self.Result(token=response.token,token_id=response.token_id,expires_at=expires_at.isoformat(),scopes=ctx.config.scopes,),self.TokenPrivateState(token=response.token),expires_at,)asyncdefrenew(self,ctx:EphemeralResourceContext[None,TokenPrivateState])->tuple[TokenPrivateState,datetime]:"""Renew token before expiration."""response=awaitself.provider.api_client.renew_token(token=ctx.private_state.token)expires_at=response.expires_atordatetime.utcnow()+timedelta(hours=1)returnself.TokenPrivateState(token=response.token),expires_atasyncdefclose(self,ctx:EphemeralResourceContext[None,TokenPrivateState])->None:"""Revoke the API token."""awaitself.provider.api_client.revoke_token(ctx.private_state.token)
# Ephemeral resource for temporary database connectionephemeral"mycloud_database_session" "main"{host="db.example.com"port=5432database="myapp"}# Use in another resourceresource"mycloud_data_import""import"{session_id=ephemeral.mycloud_database_session.main.session_idsource="s3://bucket/data.csv"}
frompyvider.exceptionsimportResourceErrorasyncdefopen(self,config:Config)->State:try:session=awaitself.provider.create_session(...)exceptConnectionErrorase:raiseResourceError(f"Failed to open session: {e}",details={"host":config.host,"port":config.port})returnself.State(...)
importpytestfrompyvider.ephemerals.contextimportEphemeralResourceContextfrommy_provider.ephemeralsimportApiToken@pytest.fixturedefapi_token():returnApiToken()@pytest.mark.asyncioasyncdeftest_token_lifecycle(api_token,mock_provider):# Setupapi_token.provider=mock_provider# Test openconfig_ctx=EphemeralResourceContext(config=ApiToken.Config(scopes=["read","write"]))result,private_state,renew_at=awaitapi_token.open(config_ctx)assertresult.token_idisnotNoneassertresult.scopes==["read","write"]# Test renewrenew_ctx=EphemeralResourceContext(private_state=private_state)new_private_state,next_renew=awaitapi_token.renew(renew_ctx)assertnext_renew>=renew_at# Test closeawaitapi_token.close(EphemeralResourceContext(private_state=new_private_state))# Verify cleanup happened