airbyte.cloud.organizations
PyAirbyte classes and methods for Airbyte Cloud organizations.
1# Copyright (c) 2024 Airbyte, Inc., all rights reserved. 2"""PyAirbyte classes and methods for Airbyte Cloud organizations.""" 3 4from __future__ import annotations 5 6import logging 7from typing import Any 8 9import requests 10 11from airbyte._util import api_util 12from airbyte.cloud._credentials import _AirbyteCredentials 13from airbyte.cloud.models import CloudOrganizationBillingInfo 14from airbyte.exceptions import AirbyteError 15from airbyte.secrets.base import SecretString 16 17 18logger = logging.getLogger(__name__) 19 20 21class CloudOrganization: 22 """Information about an organization in Airbyte Cloud. 23 24 This class provides lazy loading of organization attributes including billing status. 25 It is typically created via `CloudWorkspace.get_organization()`. 26 """ 27 28 def __init__( 29 self, 30 organization_id: str, 31 organization_name: str | None = None, 32 email: str | None = None, 33 *, 34 client_id: str | SecretString | None = None, 35 client_secret: str | SecretString | None = None, 36 bearer_token: str | SecretString | None = None, 37 public_api_root: str | None = None, 38 config_api_root: str | None = None, 39 ) -> None: 40 """Initialize a `CloudOrganization`.""" 41 self.organization_id = organization_id 42 """The organization ID.""" 43 44 self._organization_name = organization_name 45 """Display name of the organization.""" 46 47 self._email = email 48 """Email associated with the organization.""" 49 50 self._credentials = _AirbyteCredentials( 51 client_id=SecretString(client_id) if client_id else None, 52 client_secret=SecretString(client_secret) if client_secret else None, 53 bearer_token=SecretString(bearer_token) if bearer_token else None, 54 public_api_root=public_api_root or api_util.CLOUD_API_ROOT, 55 config_api_root=config_api_root, 56 organization_id=organization_id, 57 ) 58 self._organization_info: dict[str, Any] | None = None 59 self._organization_info_fetch_failed: bool = False 60 61 def _fetch_organization_info(self, *, force_refresh: bool = False) -> dict[str, Any]: 62 """Fetch and cache organization info including billing status.""" 63 if force_refresh: 64 self._organization_info_fetch_failed = False 65 66 if self._organization_info_fetch_failed and self._organization_info is None: 67 return {} 68 69 if not force_refresh and self._organization_info is not None: 70 return self._organization_info 71 72 try: 73 self._organization_info = api_util.get_organization_info( 74 organization_id=self.organization_id, 75 api_root=self._credentials.public_api_root, 76 config_api_root=self._credentials.config_api_root, 77 client_id=self._credentials.client_id, 78 client_secret=self._credentials.client_secret, 79 bearer_token=self._credentials.bearer_token, 80 ) 81 except Exception as ex: 82 logger.debug("Failed to fetch organization info.", exc_info=ex) 83 if self._organization_info is None: 84 self._organization_info_fetch_failed = True 85 return self._organization_info or {} 86 else: 87 return self._organization_info 88 89 @property 90 def organization_name(self) -> str | None: 91 """Display name of the organization.""" 92 if self._organization_name is not None: 93 return self._organization_name 94 info = self._fetch_organization_info() 95 return info.get("organizationName") 96 97 @property 98 def email(self) -> str | None: 99 """Email associated with the organization.""" 100 if self._email is not None: 101 return self._email 102 info = self._fetch_organization_info() 103 return info.get("email") 104 105 def get_billing_status(self) -> CloudOrganizationBillingInfo: 106 """Fetch billing status for the organization or raise on failure.""" 107 try: 108 info = api_util.get_organization_info( 109 organization_id=self.organization_id, 110 api_root=self._credentials.public_api_root, 111 config_api_root=self._credentials.config_api_root, 112 client_id=self._credentials.client_id, 113 client_secret=self._credentials.client_secret, 114 bearer_token=self._credentials.bearer_token, 115 ) 116 except (requests.RequestException, ValueError) as ex: 117 raise AirbyteError( 118 message="Failed to retrieve organization billing information.", 119 context={"organization_id": self.organization_id}, 120 ) from ex 121 billing = info.get("billing") 122 if not isinstance(billing, dict): 123 raise AirbyteError( 124 message="Organization info did not include billing details.", 125 context={"organization_id": self.organization_id}, 126 ) 127 payment_status = billing.get("paymentStatus") 128 subscription_status = billing.get("subscriptionStatus") 129 return CloudOrganizationBillingInfo( 130 payment_status=payment_status if isinstance(payment_status, str) else None, 131 subscription_status=( 132 subscription_status if isinstance(subscription_status, str) else None 133 ), 134 is_account_locked=api_util.is_account_locked(payment_status, subscription_status), 135 ) 136 137 @property 138 def payment_status(self) -> str | None: 139 """Payment status of the organization.""" 140 info = self._fetch_organization_info() 141 return (info.get("billing") or {}).get("paymentStatus") 142 143 @property 144 def subscription_status(self) -> str | None: 145 """Subscription status of the organization.""" 146 info = self._fetch_organization_info() 147 return (info.get("billing") or {}).get("subscriptionStatus") 148 149 @property 150 def is_account_locked(self) -> bool: 151 """Whether the account is locked due to billing issues.""" 152 return api_util.is_account_locked(self.payment_status, self.subscription_status)
logger =
<Logger airbyte.cloud.organizations (INFO)>
class
CloudOrganization:
22class CloudOrganization: 23 """Information about an organization in Airbyte Cloud. 24 25 This class provides lazy loading of organization attributes including billing status. 26 It is typically created via `CloudWorkspace.get_organization()`. 27 """ 28 29 def __init__( 30 self, 31 organization_id: str, 32 organization_name: str | None = None, 33 email: str | None = None, 34 *, 35 client_id: str | SecretString | None = None, 36 client_secret: str | SecretString | None = None, 37 bearer_token: str | SecretString | None = None, 38 public_api_root: str | None = None, 39 config_api_root: str | None = None, 40 ) -> None: 41 """Initialize a `CloudOrganization`.""" 42 self.organization_id = organization_id 43 """The organization ID.""" 44 45 self._organization_name = organization_name 46 """Display name of the organization.""" 47 48 self._email = email 49 """Email associated with the organization.""" 50 51 self._credentials = _AirbyteCredentials( 52 client_id=SecretString(client_id) if client_id else None, 53 client_secret=SecretString(client_secret) if client_secret else None, 54 bearer_token=SecretString(bearer_token) if bearer_token else None, 55 public_api_root=public_api_root or api_util.CLOUD_API_ROOT, 56 config_api_root=config_api_root, 57 organization_id=organization_id, 58 ) 59 self._organization_info: dict[str, Any] | None = None 60 self._organization_info_fetch_failed: bool = False 61 62 def _fetch_organization_info(self, *, force_refresh: bool = False) -> dict[str, Any]: 63 """Fetch and cache organization info including billing status.""" 64 if force_refresh: 65 self._organization_info_fetch_failed = False 66 67 if self._organization_info_fetch_failed and self._organization_info is None: 68 return {} 69 70 if not force_refresh and self._organization_info is not None: 71 return self._organization_info 72 73 try: 74 self._organization_info = api_util.get_organization_info( 75 organization_id=self.organization_id, 76 api_root=self._credentials.public_api_root, 77 config_api_root=self._credentials.config_api_root, 78 client_id=self._credentials.client_id, 79 client_secret=self._credentials.client_secret, 80 bearer_token=self._credentials.bearer_token, 81 ) 82 except Exception as ex: 83 logger.debug("Failed to fetch organization info.", exc_info=ex) 84 if self._organization_info is None: 85 self._organization_info_fetch_failed = True 86 return self._organization_info or {} 87 else: 88 return self._organization_info 89 90 @property 91 def organization_name(self) -> str | None: 92 """Display name of the organization.""" 93 if self._organization_name is not None: 94 return self._organization_name 95 info = self._fetch_organization_info() 96 return info.get("organizationName") 97 98 @property 99 def email(self) -> str | None: 100 """Email associated with the organization.""" 101 if self._email is not None: 102 return self._email 103 info = self._fetch_organization_info() 104 return info.get("email") 105 106 def get_billing_status(self) -> CloudOrganizationBillingInfo: 107 """Fetch billing status for the organization or raise on failure.""" 108 try: 109 info = api_util.get_organization_info( 110 organization_id=self.organization_id, 111 api_root=self._credentials.public_api_root, 112 config_api_root=self._credentials.config_api_root, 113 client_id=self._credentials.client_id, 114 client_secret=self._credentials.client_secret, 115 bearer_token=self._credentials.bearer_token, 116 ) 117 except (requests.RequestException, ValueError) as ex: 118 raise AirbyteError( 119 message="Failed to retrieve organization billing information.", 120 context={"organization_id": self.organization_id}, 121 ) from ex 122 billing = info.get("billing") 123 if not isinstance(billing, dict): 124 raise AirbyteError( 125 message="Organization info did not include billing details.", 126 context={"organization_id": self.organization_id}, 127 ) 128 payment_status = billing.get("paymentStatus") 129 subscription_status = billing.get("subscriptionStatus") 130 return CloudOrganizationBillingInfo( 131 payment_status=payment_status if isinstance(payment_status, str) else None, 132 subscription_status=( 133 subscription_status if isinstance(subscription_status, str) else None 134 ), 135 is_account_locked=api_util.is_account_locked(payment_status, subscription_status), 136 ) 137 138 @property 139 def payment_status(self) -> str | None: 140 """Payment status of the organization.""" 141 info = self._fetch_organization_info() 142 return (info.get("billing") or {}).get("paymentStatus") 143 144 @property 145 def subscription_status(self) -> str | None: 146 """Subscription status of the organization.""" 147 info = self._fetch_organization_info() 148 return (info.get("billing") or {}).get("subscriptionStatus") 149 150 @property 151 def is_account_locked(self) -> bool: 152 """Whether the account is locked due to billing issues.""" 153 return api_util.is_account_locked(self.payment_status, self.subscription_status)
Information about an organization in Airbyte Cloud.
This class provides lazy loading of organization attributes including billing status.
It is typically created via CloudWorkspace.get_organization().
CloudOrganization( organization_id: str, organization_name: str | None = None, email: str | None = None, *, client_id: str | airbyte.secrets.SecretString | None = None, client_secret: str | airbyte.secrets.SecretString | None = None, bearer_token: str | airbyte.secrets.SecretString | None = None, public_api_root: str | None = None, config_api_root: str | None = None)
29 def __init__( 30 self, 31 organization_id: str, 32 organization_name: str | None = None, 33 email: str | None = None, 34 *, 35 client_id: str | SecretString | None = None, 36 client_secret: str | SecretString | None = None, 37 bearer_token: str | SecretString | None = None, 38 public_api_root: str | None = None, 39 config_api_root: str | None = None, 40 ) -> None: 41 """Initialize a `CloudOrganization`.""" 42 self.organization_id = organization_id 43 """The organization ID.""" 44 45 self._organization_name = organization_name 46 """Display name of the organization.""" 47 48 self._email = email 49 """Email associated with the organization.""" 50 51 self._credentials = _AirbyteCredentials( 52 client_id=SecretString(client_id) if client_id else None, 53 client_secret=SecretString(client_secret) if client_secret else None, 54 bearer_token=SecretString(bearer_token) if bearer_token else None, 55 public_api_root=public_api_root or api_util.CLOUD_API_ROOT, 56 config_api_root=config_api_root, 57 organization_id=organization_id, 58 ) 59 self._organization_info: dict[str, Any] | None = None 60 self._organization_info_fetch_failed: bool = False
Initialize a CloudOrganization.
organization_name: str | None
90 @property 91 def organization_name(self) -> str | None: 92 """Display name of the organization.""" 93 if self._organization_name is not None: 94 return self._organization_name 95 info = self._fetch_organization_info() 96 return info.get("organizationName")
Display name of the organization.
email: str | None
98 @property 99 def email(self) -> str | None: 100 """Email associated with the organization.""" 101 if self._email is not None: 102 return self._email 103 info = self._fetch_organization_info() 104 return info.get("email")
Email associated with the organization.
def
get_billing_status(self) -> airbyte.cloud.models.CloudOrganizationBillingInfo:
106 def get_billing_status(self) -> CloudOrganizationBillingInfo: 107 """Fetch billing status for the organization or raise on failure.""" 108 try: 109 info = api_util.get_organization_info( 110 organization_id=self.organization_id, 111 api_root=self._credentials.public_api_root, 112 config_api_root=self._credentials.config_api_root, 113 client_id=self._credentials.client_id, 114 client_secret=self._credentials.client_secret, 115 bearer_token=self._credentials.bearer_token, 116 ) 117 except (requests.RequestException, ValueError) as ex: 118 raise AirbyteError( 119 message="Failed to retrieve organization billing information.", 120 context={"organization_id": self.organization_id}, 121 ) from ex 122 billing = info.get("billing") 123 if not isinstance(billing, dict): 124 raise AirbyteError( 125 message="Organization info did not include billing details.", 126 context={"organization_id": self.organization_id}, 127 ) 128 payment_status = billing.get("paymentStatus") 129 subscription_status = billing.get("subscriptionStatus") 130 return CloudOrganizationBillingInfo( 131 payment_status=payment_status if isinstance(payment_status, str) else None, 132 subscription_status=( 133 subscription_status if isinstance(subscription_status, str) else None 134 ), 135 is_account_locked=api_util.is_account_locked(payment_status, subscription_status), 136 )
Fetch billing status for the organization or raise on failure.
payment_status: str | None
138 @property 139 def payment_status(self) -> str | None: 140 """Payment status of the organization.""" 141 info = self._fetch_organization_info() 142 return (info.get("billing") or {}).get("paymentStatus")
Payment status of the organization.