Skip to content

Commit

Permalink
Fixing lint issues
Browse files Browse the repository at this point in the history
feat: Adding utilities to connect AWS services like RDS

adding AWS Dataservices connectors utilities

----
Signed-off-by: Saisharath <srsharathreddy@gmail.com>
  • Loading branch information
skondakindi committed Apr 8, 2024
1 parent ed7e899 commit f54d76e
Show file tree
Hide file tree
Showing 18 changed files with 383 additions and 188 deletions.
54 changes: 32 additions & 22 deletions numalogic/connectors/rds/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,47 @@

class RDSDataFetcher:
"""
Class: RDSDataFetcher
Class: RDSDataFetcher.
This class represents a data fetcher for RDS (Relational Database Service) connections. It
provides methods for retrieving the RDS token, getting the password, establishing a
connection, and executing queries.
Attributes:
Attributes
----------
- db_config (RDSConfig): The configuration object for the RDS connection.
- kwargs (dict): Additional keyword arguments.
Methods:
Methods
-------
- get_rds_token(): Retrieves the RDS token using the Boto3ClientManager. - get_password() ->
str: Retrieves the password for the RDS connection. If 'aws_rds_use_iam' is True, it calls
the get_rds_token() method, otherwise it returns the database password from the
configuration. - get_connection(): Placeholder method for establishing a connection to the
RDS database. - get_db_cursor(): Placeholder method for getting a database cursor. -
execute_query(query) -> pd.DataFrame: Placeholder method for executing a query and returning
the result as a pandas DataFrame.
"""

def __init__(self, db_config: RDSConfig, **kwargs):
"""
Initialize an instance of the RDSDataFetcher class.
Parameters:
Parameters
----------
- db_config (RDSConfig): The configuration object for the RDS connection.
- kwargs (dict): Additional keyword arguments.
Attributes:
Attributes
----------
- self.kwargs (dict): Additional keyword arguments.
- self.db_config (RDSConfig): The configuration object for the RDS connection.
- self.connection (None): The connection object for the RDS database.
- self.database_type (str): The type of the database.
Returns:
Returns
-------
- None
"""
Expand All @@ -58,16 +62,18 @@ def get_rds_token(self):
"""
Generates an RDS authentication token using the provided RDS boto3 client.
Parameters: rds_boto3_client (boto3.client): The RDS boto3 client used to generate the
Parameters
----------
- rds_boto3_client (boto3.client): The RDS boto3 client used to generate the
authentication token.
Returns:
Returns
-------
str: The generated RDS authentication token.
"""
rds_client = self.boto3_client_manager.get_client(DatabaseServiceProvider.rds.value)
db_password = self.boto3_client_manager.get_rds_token(rds_client)
return db_password
return self.boto3_client_manager.get_rds_token(rds_client)

def get_password(self) -> str:
"""
Expand All @@ -76,19 +82,19 @@ def get_password(self) -> str:
If 'aws_rds_use_iam' is True, it calls the get_rds_token() method to generate the RDS
token. Otherwise, it returns the database password from the configuration.
Returns:
Returns
-------
str: The password for the RDS connection.
"""
db_password = None
password = None
if self.db_config.aws_rds_use_iam:
_LOGGER.info("using aws_rds_use_iam to generate RDS Token")
db_password = self.get_rds_token()
return db_password
password = self.get_rds_token()
else:
_LOGGER.info("using password from config to connect RDS Database")
db_password = self.db_config.database_password
return db_password
password = self.db_config.database_password
return password

def get_connection(self):
"""
Expand All @@ -98,7 +104,8 @@ def get_connection(self):
the logic for establishing a connection to the RDS database based on the provided
configuration.
Returns:
Returns
-------
None
"""
Expand All @@ -111,7 +118,8 @@ def get_db_cursor(self):
This method is a placeholder and needs to be implemented in a subclass. It should handle
the logic for retrieving a database cursor based on the established connection.
Returns:
Returns
-------
None
"""
Expand All @@ -121,10 +129,12 @@ def execute_query(self, query) -> pd.DataFrame:
"""
Executes a query on the RDS database and returns the result as a pandas DataFrame.
Parameters:
Parameters
----------
query (str): The SQL query to be executed.
Returns:
Returns
-------
pd.DataFrame: The result of the query as a pandas DataFrame.
"""
Expand Down
17 changes: 11 additions & 6 deletions numalogic/connectors/rds/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ class DatabaseServiceProvider(BaseEnum):
"""
A class representing the database service providers.
Attributes:
Attributes
----------
rds (str): Represents the RDS (Relational Database Service) provider.
athena (str): Represents the Athena provider.
Expand All @@ -22,7 +23,8 @@ class DatabaseTypes(BaseEnum):
"""
A class representing different types of databases.
Attributes:
Attributes
----------
mysql (str): Represents the MySQL database type.
athena (str): Represents the Athena database type.
"""
Expand All @@ -36,7 +38,8 @@ class AWSConfig:
"""
Class representing AWS configuration.
Attributes:
Attributes
----------
aws_assume_role_arn (str): The ARN of the IAM role to assume.
aws_assume_role_session_name (str): The name of the session when assuming the IAM role.
"""
Expand Down Expand Up @@ -64,7 +67,9 @@ class RDBMSConfig:
RDBMSConfig class represents the configuration for a Relational Database Management System (
RDBMS).
Attributes: endpoint (str): The endpoint or hostname of the database. Defaults to an empty
Attributes
----------
endpoint (str): The endpoint or hostname of the database. Defaults to an empty
string.
port (int): The port number of the database. Defaults to 3306.
database_name (str): The name of the database. Defaults to an empty string.
Expand Down Expand Up @@ -100,8 +105,8 @@ class RDSConfig(AWSConfig, RDBMSConfig):
Inherits from: - AWSConfig: Class representing AWS configuration. - RDBMSConfig: Class
representing the configuration for a Relational Database Management System (RDBMS).
Attributes:
Attributes
----------
aws_assume_role_arn (str): The ARN of the IAM role to assume.
aws_assume_role_session_name (str): The name of the session when assuming the IAM role.
endpoint (str): The endpoint or hostname of the database. Defaults to an empty string.
Expand Down
19 changes: 12 additions & 7 deletions numalogic/connectors/rds/_rds.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,39 @@
_LOGGER = logging.getLogger(__name__)


class RDSFetcher(object):
class RDSFetcher:

def __init__(self, db_config: RDSConfig):
"""
Initialize an instance of the RDSFetcher class.
Parameters:
Parameters
----------
db_config (RDSConfig): The configuration for the RDS instance.
Returns:
Returns
-------
None
Raises:
Raises
------
None
"""
self.db_config = db_config
if db.CLASS_TYPE:
self.fetcher = db.CLASS_TYPE(db_config)
_LOGGER.info(f"Executing for database type: {self.fetcher.database_type}")
_LOGGER.info("Executing for database type: %s", self.fetcher.database_type)

def fetch(self, query) -> pd.DataFrame:
"""
Fetches data from the RDS instance by executing the given query.
Parameters:
Parameters
----------
query (str): The SQL query to be executed.
Returns:
Returns
-------
pd.DataFrame: A pandas DataFrame containing the fetched data.
"""
Expand Down
47 changes: 28 additions & 19 deletions numalogic/connectors/rds/db/MYSQLFetcher.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
from numalogic.connectors.rds._base import RDSDataFetcher
import os
import pymysql
import pandas as pd
import logging

from numalogic.connectors.rds._config import DatabaseTypes, RDSConfig
from numalogic.connectors.utils.aws.db_configurations import load_db_conf

_LOGGER = logging.getLogger(__name__)


class MYSQLFetcher(RDSDataFetcher):
"""
This code snippet defines a class called MYSQLFetcher that inherits from RDSDataFetcher. It
is used to fetch data from a MySQL database. The class has several methods:
MYSQLFetcher that inherits from RDSDataFetcher. It is used to fetch data from a MySQL database.
The class has several methods:
- __init__(self, db_config: RDSConfig, **kwargs): Initializes the MYSQLFetcher object with
the given RDSConfig and additional keyword arguments. - get_connection(self): Establishes a
Expand All @@ -27,21 +26,23 @@ class MYSQLFetcher(RDSDataFetcher):
and retrieving the results. The class can be extended and customized as needed for specific
use cases.
"""

database_type = DatabaseTypes.mysql.value

def __init__(self, db_config: RDSConfig, **kwargs):
"""
Initializes the MYSQLFetcher object with the given RDSConfig and additional keyword
arguments.
Parameters:
Parameters
----------
- db_config (RDSConfig): The configuration object for the RDS connection.
- **kwargs: Additional keyword arguments.
Returns:
Returns
-------
None
"""

super().__init__(db_config)
self.db_config = db_config
self.kwargs = kwargs
Expand All @@ -50,10 +51,12 @@ def get_connection(self):
"""
Establishes a connection to the MySQL database using the provided configuration.
Returns:
Returns
-------
pymysql.connections.Connection: The connection object for the MySQL database.
Raises:
Raises
------
None
Notes: - If SSL/TLS is enabled and configured in the RDSConfig object, the connection
Expand All @@ -62,6 +65,7 @@ def get_connection(self):
for further use in executing queries on the database.
"""
connection = None
if self.db_config.ssl and self.db_config.ssl_enabled:
connection = pymysql.connect(
host=self.db_config.endpoint,
Expand All @@ -74,7 +78,6 @@ def get_connection(self):
charset="utf8mb4",
connect_timeout=self.db_config.database_connection_timeout,
)
return connection
else:
connection = pymysql.connect(
host=self.db_config.endpoint,
Expand All @@ -86,7 +89,8 @@ def get_connection(self):
charset="utf8mb4",
connect_timeout=self.db_config.database_connection_timeout,
)
return connection

return connection

def get_db_cursor(self, connection):
"""
Expand All @@ -95,31 +99,36 @@ def get_db_cursor(self, connection):
Parameters: - connection (pymysql.connections.Connection): The connection object for the
MySQL database.
Returns:
Returns
-------
pymysql.cursors.Cursor: The cursor object for executing queries on the database.
Raises:
Raises
------
None
Notes:
Notes
-----
- The cursor object is used to execute queries on the database.
- The connection object must be established before calling this method.
"""
cursor = connection.cursor()
return cursor
return connection.cursor()

def execute_query(self, query) -> pd.DataFrame:
"""
Executes the given query on the database and returns the result as a pandas DataFrame.
Parameters:
Parameters
----------
- query (str): The SQL query to be executed on the database.
Returns:
Returns
-------
pd.DataFrame: The result of the query as a pandas DataFrame.
Raises:
Raises
------
None
Notes: - This method establishes a connection to the database using the get_connection()
Expand Down
13 changes: 7 additions & 6 deletions numalogic/connectors/rds/db/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
# value is an array of classes
CLASS_TYPE = None

"""This code snippet is a loop that iterates over the files in the directory of the current file. It checks if each
file ends with "Fetcher.py" and if so, extracts the class name by removing the ".py" extension. It then imports the
module corresponding to the class and retrieves the class object using the class name. Finally, it assigns the class
object to the CLASS_TYPE variable. This code snippet is used to dynamically import and assign class objects based on
file names."""
"""This code snippet is a loop that iterates over the files in the directory of the current
file. It checks if each file ends with "Fetcher.py" and if so, extracts the class name by
removing the ".py" extension. It then imports the module corresponding to the class and
retrieves the class object using the class name. Finally, it assigns the class object to the
CLASS_TYPE variable. This code snippet is used to dynamically import and assign class objects
based on file names."""

for file_name in os.listdir(os.path.dirname(__file__)):
if file_name.endswith("Fetcher.py"):
class_name = file_name[:-3]
module = importlib.import_module(f'.{class_name}', __name__)
module = importlib.import_module(f".{class_name}", __name__)
CLASS_TYPE = getattr(module, class_name)
Loading

0 comments on commit f54d76e

Please sign in to comment.