Source code for runloop_api_client.sdk.async_secret

"""Secret resource class for asynchronous operations."""

from __future__ import annotations

from typing_extensions import Unpack, override

from ._types import BaseRequestOptions, LongRequestOptions
from .._client import AsyncRunloop
from ..types.secret_view import SecretView


[docs] class AsyncSecret: """Asynchronous wrapper around a secret resource. Secrets are encrypted key-value pairs that can be securely stored and injected into Devboxes as environment variables. This wrapper always operates by its account-scoped name, even if it contains an ID from an earlier response. Reads and updates select the greatest ID at lookup; deletion removes all selected matches, nonatomically. Use ``sdk.secret.from_id(id)`` for exact row operations. Example: >>> runloop = AsyncRunloopSDK() >>> secret = await runloop.secret.create( ... name="MY_API_KEY", ... value="secret-value", ... ) >>> info = await secret.get_info() >>> print(f"Secret: {info.name}, ID: {info.id}") """ def __init__( self, client: AsyncRunloop, name: str, id: str | None = None, ) -> None: """Initialize the wrapper. :param client: Generated AsyncRunloop client :type client: AsyncRunloop :param name: The literal account-scoped name of the secret :type name: str :param id: The secret ID (optional, may not be known until get_info is called) :type id: str | None """ self._client = client self._name = name self._id = id @override def __repr__(self) -> str: return f"<AsyncSecret name={self._name!r}>" @property def id(self) -> str | None: """Return the secret ID. :return: Captured response ID, or None. Fetching metadata does not refresh this property. :rtype: str | None """ return self._id @property def name(self) -> str: """Return the secret name. :return: Literal account-scoped secret name :rtype: str """ return self._name
[docs] async def get_info( self, **options: Unpack[BaseRequestOptions], ) -> SecretView: """Retrieve the latest secret details from the API. Note: The secret value is never returned for security reasons. Example: >>> info = await secret.get_info() >>> print(f"Secret: {info.name}, ID: {info.id}, Created: {info.create_time_ms}") :param options: Optional request configuration :return: API response describing the secret (value not included) :rtype: SecretView """ return await self._client.secrets.retrieve( self._name, **options, )
[docs] async def update( self, value: str, **options: Unpack[LongRequestOptions], ) -> SecretView: """Update the greatest-ID row matching this name at lookup. This wrapper remains name-bound and its captured ID is unchanged. Example: >>> updated = await secret.update("new-secret-value") >>> print(f"Updated at: {updated.update_time_ms}") :param value: The new secret value (will be encrypted at rest) :type value: str :param options: Optional request configuration :return: Updated secret view :rtype: SecretView """ return await self._client.secrets.update( self._name, value=value, **options, )
[docs] async def delete( self, **options: Unpack[LongRequestOptions], ) -> SecretView: """Delete every selected row matching this name, nonatomically. A concurrent create can survive. This action is irreversible. Example: >>> await secret.delete() :param options: Optional long-running request configuration :return: API response acknowledging deletion :rtype: SecretView """ return await self._client.secrets.delete( self._name, **options, )