AmmarFahmy
adding all files
105b369
from typing import Any, Optional
from phi.resource.base import ResourceBase
from phi.aws.api_client import AwsApiClient
from phi.cli.console import print_info
from phi.utils.log import logger
class AwsResource(ResourceBase):
service_name: str
service_client: Optional[Any] = None
service_resource: Optional[Any] = None
aws_region: Optional[str] = None
aws_profile: Optional[str] = None
aws_client: Optional[AwsApiClient] = None
def get_aws_region(self) -> Optional[str]:
# Priority 1: Use aws_region from resource
if self.aws_region:
return self.aws_region
# Priority 2: Get aws_region from workspace settings
if self.workspace_settings is not None and self.workspace_settings.aws_region is not None:
self.aws_region = self.workspace_settings.aws_region
return self.aws_region
# Priority 3: Get aws_region from env
from os import getenv
from phi.constants import AWS_REGION_ENV_VAR
aws_region_env = getenv(AWS_REGION_ENV_VAR)
if aws_region_env is not None:
logger.debug(f"{AWS_REGION_ENV_VAR}: {aws_region_env}")
self.aws_region = aws_region_env
return self.aws_region
def get_aws_profile(self) -> Optional[str]:
# Priority 1: Use aws_region from resource
if self.aws_profile:
return self.aws_profile
# Priority 2: Get aws_profile from workspace settings
if self.workspace_settings is not None and self.workspace_settings.aws_profile is not None:
self.aws_profile = self.workspace_settings.aws_profile
return self.aws_profile
# Priority 3: Get aws_profile from env
from os import getenv
from phi.constants import AWS_PROFILE_ENV_VAR
aws_profile_env = getenv(AWS_PROFILE_ENV_VAR)
if aws_profile_env is not None:
logger.debug(f"{AWS_PROFILE_ENV_VAR}: {aws_profile_env}")
self.aws_profile = aws_profile_env
return self.aws_profile
def get_service_client(self, aws_client: AwsApiClient):
from boto3 import session
if self.service_client is None:
boto3_session: session = aws_client.boto3_session
self.service_client = boto3_session.client(service_name=self.service_name)
return self.service_client
def get_service_resource(self, aws_client: AwsApiClient):
from boto3 import session
if self.service_resource is None:
boto3_session: session = aws_client.boto3_session
self.service_resource = boto3_session.resource(service_name=self.service_name)
return self.service_resource
def get_aws_client(self) -> AwsApiClient:
if self.aws_client is not None:
return self.aws_client
self.aws_client = AwsApiClient(aws_region=self.get_aws_region(), aws_profile=self.get_aws_profile())
return self.aws_client
def _read(self, aws_client: AwsApiClient) -> Any:
logger.warning(f"@_read method not defined for {self.get_resource_name()}")
return True
def read(self, aws_client: Optional[AwsApiClient] = None) -> Any:
"""Reads the resource from Aws"""
# Step 1: Use cached value if available
if self.use_cache and self.active_resource is not None:
return self.active_resource
# Step 2: Skip resource creation if skip_read = True
if self.skip_read:
print_info(f"Skipping read: {self.get_resource_name()}")
return True
# Step 3: Read resource
client: AwsApiClient = aws_client or self.get_aws_client()
return self._read(client)
def is_active(self, aws_client: AwsApiClient) -> bool:
"""Returns True if the resource is active on Aws"""
_resource = self.read(aws_client=aws_client)
return True if _resource is not None else False
def _create(self, aws_client: AwsApiClient) -> bool:
logger.warning(f"@_create method not defined for {self.get_resource_name()}")
return True
def create(self, aws_client: Optional[AwsApiClient] = None) -> bool:
"""Creates the resource on Aws"""
# Step 1: Skip resource creation if skip_create = True
if self.skip_create:
print_info(f"Skipping create: {self.get_resource_name()}")
return True
# Step 2: Check if resource is active and use_cache = True
client: AwsApiClient = aws_client or self.get_aws_client()
if self.use_cache and self.is_active(client):
self.resource_created = True
print_info(f"{self.get_resource_type()}: {self.get_resource_name()} already exists")
# Step 3: Create the resource
else:
self.resource_created = self._create(client)
if self.resource_created:
print_info(f"{self.get_resource_type()}: {self.get_resource_name()} created")
# Step 4: Run post create steps
if self.resource_created:
if self.save_output:
self.save_output_file()
logger.debug(f"Running post-create for {self.get_resource_type()}: {self.get_resource_name()}")
return self.post_create(client)
logger.error(f"Failed to create {self.get_resource_type()}: {self.get_resource_name()}")
return self.resource_created
def post_create(self, aws_client: AwsApiClient) -> bool:
return True
def _update(self, aws_client: AwsApiClient) -> Any:
logger.warning(f"@_update method not defined for {self.get_resource_name()}")
return True
def update(self, aws_client: Optional[AwsApiClient] = None) -> bool:
"""Updates the resource on Aws"""
# Step 1: Skip resource update if skip_update = True
if self.skip_update:
print_info(f"Skipping update: {self.get_resource_name()}")
return True
# Step 2: Update the resource
client: AwsApiClient = aws_client or self.get_aws_client()
if self.is_active(client):
self.resource_updated = self._update(client)
else:
print_info(f"{self.get_resource_type()}: {self.get_resource_name()} does not exist")
return True
# Step 3: Run post update steps
if self.resource_updated:
print_info(f"{self.get_resource_type()}: {self.get_resource_name()} updated")
if self.save_output:
self.save_output_file()
logger.debug(f"Running post-update for {self.get_resource_type()}: {self.get_resource_name()}")
return self.post_update(client)
logger.error(f"Failed to update {self.get_resource_type()}: {self.get_resource_name()}")
return self.resource_updated
def post_update(self, aws_client: AwsApiClient) -> bool:
return True
def _delete(self, aws_client: AwsApiClient) -> Any:
logger.warning(f"@_delete method not defined for {self.get_resource_name()}")
return True
def delete(self, aws_client: Optional[AwsApiClient] = None) -> bool:
"""Deletes the resource from Aws"""
# Step 1: Skip resource deletion if skip_delete = True
if self.skip_delete:
print_info(f"Skipping delete: {self.get_resource_name()}")
return True
# Step 2: Delete the resource
client: AwsApiClient = aws_client or self.get_aws_client()
if self.is_active(client):
self.resource_deleted = self._delete(client)
else:
print_info(f"{self.get_resource_type()}: {self.get_resource_name()} does not exist")
return True
# Step 3: Run post delete steps
if self.resource_deleted:
print_info(f"{self.get_resource_type()}: {self.get_resource_name()} deleted")
if self.save_output:
self.delete_output_file()
logger.debug(f"Running post-delete for {self.get_resource_type()}: {self.get_resource_name()}.")
return self.post_delete(client)
logger.error(f"Failed to delete {self.get_resource_type()}: {self.get_resource_name()}")
return self.resource_deleted
def post_delete(self, aws_client: AwsApiClient) -> bool:
return True