Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Google Cloud SQL MySQL Connector #4949

Merged
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
7785f1e
Some steps forward integration Google Cloud SQL
andres-torres-marroquin May 24, 2024
4e59a66
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
andres-torres-marroquin Jun 3, 2024
d52fb51
Updates Google Cloud SQL MySQL Integration
andres-torres-marroquin Jun 3, 2024
e0d0101
Updates Google Cloud SQL MySQL Integration
andres-torres-marroquin Jun 4, 2024
40c0168
Updates Google Cloud SQL MySQL Integration
andres-torres-marroquin Jun 4, 2024
de71c40
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
andres-torres-marroquin Jun 4, 2024
b745c69
Updates Google Cloud SQL MySQL Integration
andres-torres-marroquin Jun 4, 2024
3f3fa9a
Updates Google Cloud SQL MySQL Integration
andres-torres-marroquin Jun 4, 2024
4e71a1c
Updates Google Cloud SQL MySQL Integration
andres-torres-marroquin Jun 5, 2024
0dc27df
Updates Google Cloud SQL MySQL Integration
andres-torres-marroquin Jun 6, 2024
6979b27
Updates Google Cloud SQL MySQL Integration
andres-torres-marroquin Jun 6, 2024
2109ed3
Update noxfiles/setup_tests_nox.py
andres-torres-marroquin Jun 10, 2024
f19cfe8
Update src/fides/api/service/connectors/sql_connector.py
andres-torres-marroquin Jun 10, 2024
60bd835
QA
andres-torres-marroquin Jun 10, 2024
67fe4ea
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
andres-torres-marroquin Jun 10, 2024
7de7c14
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
andres-torres-marroquin Jun 11, 2024
ab5c6a1
QA
andres-torres-marroquin Jun 11, 2024
54aa62f
QA
andres-torres-marroquin Jun 11, 2024
b7bdc8e
QA
andres-torres-marroquin Jun 12, 2024
f856d1c
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
andres-torres-marroquin Jun 12, 2024
a24cad9
QA
andres-torres-marroquin Jun 12, 2024
73530c8
QA
andres-torres-marroquin Jun 12, 2024
77a8b4f
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
andres-torres-marroquin Jun 12, 2024
6c16fdc
QA
andres-torres-marroquin Jun 12, 2024
3c0e61b
QA
andres-torres-marroquin Jun 12, 2024
ca5943a
QA
andres-torres-marroquin Jun 13, 2024
04110cc
QA
andres-torres-marroquin Jun 13, 2024
0fb4f91
QA
andres-torres-marroquin Jun 13, 2024
09c0a7a
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
andres-torres-marroquin Jun 13, 2024
1c2a3c9
QA
andres-torres-marroquin Jun 14, 2024
cb46034
QA
andres-torres-marroquin Jun 17, 2024
7f3bc61
QA
andres-torres-marroquin Jun 17, 2024
da682bf
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
galvana Jun 17, 2024
b59ee98
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
galvana Jun 17, 2024
e6ba1a3
Adding icon for Google Cloud SQL
galvana Jun 17, 2024
4a5f3d4
Adding last test for GCP on the request runner
andres-torres-marroquin Jun 18, 2024
a9fec2a
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
andres-torres-marroquin Jun 18, 2024
286afac
QA
andres-torres-marroquin Jun 18, 2024
f99cf3f
Last bits of QA
andres-torres-marroquin Jun 18, 2024
b0392a3
Update data/dataset/google_cloud_sql_mysql_example_test_dataset.yml
andres-torres-marroquin Jun 18, 2024
e62fcab
Last bits of QA
andres-torres-marroquin Jun 18, 2024
5458b89
Update noxfiles/setup_tests_nox.py
andres-torres-marroquin Jun 18, 2024
58f188c
Update noxfiles/setup_tests_nox.py
andres-torres-marroquin Jun 18, 2024
ace74df
QA
andres-torres-marroquin Jun 18, 2024
4b0cce9
QA
andres-torres-marroquin Jun 18, 2024
bfb908a
Typo fix
galvana Jun 18, 2024
fb5f3ca
QA
andres-torres-marroquin Jun 18, 2024
347dad0
Adding missing env variables for external tests
galvana Jun 18, 2024
659f0cc
Fixing test markers
galvana Jun 18, 2024
00d36bf
Adding missing imports
galvana Jun 19, 2024
8e87792
Removing Google Cloud SQL tests from Safe-Tests and fixing dataset
galvana Jun 19, 2024
43bea8e
Merge branch 'main' into PROD-2084-Google-Cloud-SQL-Integration-DSRs
galvana Jun 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
"human_readable": "MySQL",
"encoded_icon": null
},
{
"identifier": "google_cloud_mysql",
"type": "database",
"human_readable": "Google Cloud for MySQL",
andres-torres-marroquin marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"human_readable": "Google Cloud for MySQL",
"human_readable": "Google Cloud SQL for MySQL",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

"encoded_icon": null
},
{
"identifier": "postgres",
"type": "database",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""add google_cloud_mysql to connectiontype

Revision ID: d7449292621d
Revises: 4b2eade4353c
Create Date: 2024-06-03 17:29:38.233347

"""
from alembic import op


# revision identifiers, used by Alembic.
revision = 'd7449292621d'
down_revision = '4b2eade4353c'
branch_labels = None
depends_on = None



def upgrade():
# Add google_cloud_mysql to ConnectionType enum
op.execute("alter type connectiontype rename to connectiontype_old")
op.execute(
"create type connectiontype as enum('postgres', 'mongodb', 'mysql', 'https', 'snowflake', 'redshift', 'mssql', 'mariadb', 'bigquery', 'saas', 'manual', 'email', 'manual_webhook', 'timescale', 'fides', 'sovrn', 'google_cloud_mysql')"
)
op.execute(
(
"alter table connectionconfig alter column connection_type type connectiontype using "
"connection_type::text::connectiontype"
)
)
op.execute("drop type connectiontype_old")



def downgrade():
# Remove google_cloud_mysql from the ConnectionType enum
op.execute("alter type connectiontype rename to connectiontype_old")
op.execute(
"create type connectiontype as enum('postgres', 'mongodb', 'mysql', 'https', 'snowflake', 'redshift', 'mssql', 'mariadb', 'bigquery', 'saas', 'manual', 'email', 'manual_webhook', 'timescale', 'fides', 'sovrn')"
)
op.execute(
(
"alter table connectionconfig alter column connection_type type connectiontype using "
"connection_type::text::connectiontype"
)
)
op.execute("drop type connectiontype_old")
4 changes: 3 additions & 1 deletion src/fides/api/models/connectionconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class ConnectionType(enum.Enum):
postgres = "postgres"
mongodb = "mongodb"
mysql = "mysql"
google_cloud_mysql = "google_cloud_mysql"
https = "https"
saas = "saas"
redshift = "redshift"
Expand Down Expand Up @@ -66,9 +67,10 @@ def human_readable(self) -> str:
ConnectionType.fides.value: "Fides Connector",
ConnectionType.generic_consent_email.value: "Generic Consent Email",
ConnectionType.generic_erasure_email.value: "Generic Erasure Email",
ConnectionType.google_cloud_mysql.value: "Google Cloud for MySQL",
ConnectionType.https.value: "Policy Webhook",
ConnectionType.manual.value: "Manual Connector",
ConnectionType.manual_webhook.value: "Manual Process",
ConnectionType.manual.value: "Manual Connector",
ConnectionType.mariadb.value: "MariaDB",
ConnectionType.mongodb.value: "MongoDB",
ConnectionType.mssql.value: "Microsoft SQL Server",
Expand Down
32 changes: 6 additions & 26 deletions src/fides/api/schemas/connection_configuration/__init__.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll notice there's a few Static-Checks failures in the pipeline https://github.com/ethyca/fides/actions/runs/9405253983/job/25905996405?pr=4949. You can avoid this by running nox -s static_checks locally and addressing any Mypy or Pylint errors before pushing up your changes. This should take care of all the formatting changes in this and other files.

Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,15 @@
)
from fides.api.schemas.connection_configuration.connection_secrets_bigquery import (
BigQueryDocsSchema as BigQueryDocsSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_bigquery import (
BigQuerySchema as BigQuerySchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_dynamodb import (
DynamoDBDocsSchema as DynamoDBDocsSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_dynamodb import (
DynamoDBSchema as DynamoDBSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_email import (
EmailDocsSchema as EmailDocsSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_email import (
EmailSchema as EmailSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_email import (
ExtendedEmailSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_fides import (
Expand All @@ -40,56 +32,42 @@
)
from fides.api.schemas.connection_configuration.connection_secrets_manual_webhook import (
ManualWebhookSchema as ManualWebhookSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_manual_webhook import (
ManualWebhookSchemaforDocs as ManualWebhookSchemaforDocs,
)
from fides.api.schemas.connection_configuration.connection_secrets_mariadb import (
MariaDBDocsSchema as MariaDBDocsSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_mariadb import (
MariaDBSchema as MariaDBSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_mongodb import (
MongoDBDocsSchema as MongoDBDocsSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_mongodb import (
MongoDBSchema as MongoDBSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_mssql import (
MicrosoftSQLServerSchema as MicrosoftSQLServerSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_mssql import (
MSSQLDocsSchema as MSSQLDocsSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_mysql import (
MySQLDocsSchema as MySQLDocsSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_mysql import (
MySQLSchema as MySQLSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_postgres import (
PostgreSQLDocsSchema as PostgreSQLDocsSchema,
from fides.api.schemas.connection_configuration.connection_secrets_google_cloud_mysql import (
GoogleCloudMySQLDocsSchema as GoogleCloudMySQLDocsSchema,
GoogleCloudMySQLSchema as GoogleCloudMySQLSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_postgres import (
PostgreSQLDocsSchema as PostgreSQLDocsSchema,
PostgreSQLSchema as PostgreSQLSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_redshift import (
RedshiftDocsSchema as RedshiftDocsSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_redshift import (
RedshiftSchema as RedshiftSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_saas import (
SaaSSchema as SaaSSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_saas import (
SaaSSchemaFactory as SaaSSchemaFactory,
)
from fides.api.schemas.connection_configuration.connection_secrets_snowflake import (
SnowflakeDocsSchema as SnowflakeDocsSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_snowflake import (
SnowflakeSchema as SnowflakeSchema,
)
from fides.api.schemas.connection_configuration.connection_secrets_sovrn import (
Expand All @@ -114,6 +92,7 @@
ConnectionType.fides.value: FidesConnectorSchema,
ConnectionType.generic_consent_email.value: ExtendedEmailSchema,
ConnectionType.generic_erasure_email.value: EmailSchema,
ConnectionType.google_cloud_mysql.value: GoogleCloudMySQLSchema,
ConnectionType.https.value: HttpsSchema,
ConnectionType.manual_webhook.value: ManualWebhookSchema,
ConnectionType.mariadb.value: MariaDBSchema,
Expand Down Expand Up @@ -159,6 +138,7 @@ def get_connection_secrets_schema(
MongoDBDocsSchema,
PostgreSQLDocsSchema,
MySQLDocsSchema,
GoogleCloudMySQLDocsSchema,
RedshiftDocsSchema,
SnowflakeDocsSchema,
MSSQLDocsSchema,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from typing import List, Optional

from pydantic import Field

from fides.api.schemas.base_class import NoValidationSchema
from fides.api.schemas.connection_configuration.connection_secrets import (
ConnectionConfigSecretsSchema,
)


class GoogleCloudMySQLSchema(ConnectionConfigSecretsSchema):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be using Google's keyfile_creds similar to how we do it in connection_secrets_bigquery. Take a look at option two in this doc for how to authenticate using a keyfile https://ethyca.atlassian.net/wiki/spaces/EN/pages/3029204995/2024-04-19+Google+Cloud+SQL+Integration#Option-2-(IAM-database-authentication)

"""Schema to validate the secrets needed to connect to a Google Cloud MySQL Database"""

host: str = Field(
title="Host",
description="The hostname or IP address of the server where the database is running.",
)
port: int = Field(
3306,
title="Port",
description="The network port number on which the server is listening for incoming connections (default: 3306).",
)
username: Optional[str] = Field(
None,
title="Username",
description="The user account used to authenticate and access the database.",
)
password: Optional[str] = Field(
None,
title="Password",
description="The password used to authenticate and access the database.",
sensitive=True,
)
dbname: str = Field(
description="The name of the specific database within the database server that you want to connect to.",
title="Database",
)
ssh_required: bool = Field(
False,
title="SSH required",
description="Indicates whether an SSH tunnel is required for the connection. Enable this option if your Google Cloud MySQL server is behind a firewall and requires SSH tunneling for remote connections.",
)

_required_components: List[str] = ["host", "dbname"]


class GoogleCloudMySQLDocsSchema(GoogleCloudMySQLSchema, NoValidationSchema):
"""Google Cloud MySQL Secrets Schema for API Docs"""
14 changes: 3 additions & 11 deletions src/fides/api/service/connectors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,12 @@
from fides.api.service.connectors.saas_connector import SaaSConnector as SaaSConnector
from fides.api.service.connectors.sql_connector import (
BigQueryConnector as BigQueryConnector,
)
from fides.api.service.connectors.sql_connector import (
GoogleCloudMySQLConnector as GoogleCloudMySQLConnector,
MariaDBConnector as MariaDBConnector,
)
from fides.api.service.connectors.sql_connector import (
MicrosoftSQLServerConnector as MicrosoftSQLServerConnector,
)
from fides.api.service.connectors.sql_connector import MySQLConnector as MySQLConnector
from fides.api.service.connectors.sql_connector import (
MySQLConnector as MySQLConnector,
PostgreSQLConnector as PostgreSQLConnector,
)
from fides.api.service.connectors.sql_connector import (
RedshiftConnector as RedshiftConnector,
)
from fides.api.service.connectors.sql_connector import (
SnowflakeConnector as SnowflakeConnector,
)
from fides.api.service.connectors.timescale_connector import (
Expand All @@ -61,6 +52,7 @@
ConnectionType.fides.value: FidesConnector,
ConnectionType.generic_consent_email.value: GenericConsentEmailConnector,
ConnectionType.generic_erasure_email.value: GenericErasureEmailConnector,
ConnectionType.google_cloud_mysql.value: GoogleCloudMySQLConnector,
ConnectionType.https.value: HTTPSConnector,
ConnectionType.manual_webhook.value: ManualWebhookConnector,
ConnectionType.mariadb.value: MariaDBConnector,
Expand Down
4 changes: 4 additions & 0 deletions src/fides/api/service/connectors/sql_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,3 +577,7 @@ def cursor_result_to_rows(results: LegacyCursorResult) -> List[Row]:
Convert SQLAlchemy results to a list of dictionaries
"""
return SQLConnector.default_cursor_result_to_rows(results)


class GoogleCloudMySQLConnector(MySQLConnector):
"""Connector specific to Google Cloud for MySQL"""
andres-torres-marroquin marked this conversation as resolved.
Show resolved Hide resolved
7 changes: 7 additions & 0 deletions tests/fixtures/application_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@
"username": pydash.get(integration_config, "mysql_example.user"),
"password": pydash.get(integration_config, "mysql_example.password"),
},
"google_cloud_mysql": {
"host": pydash.get(integration_config, "google_cloud_mysql.server"),
"port": pydash.get(integration_config, "google_cloud_mysql.port"),
"dbname": pydash.get(integration_config, "google_cloud_mysql.db"),
"username": pydash.get(integration_config, "google_cloud_mysql.user"),
"password": pydash.get(integration_config, "google_cloud_mysql.password"),
},
"mssql_example": {
"host": pydash.get(integration_config, "mssql_example.server"),
"port": pydash.get(integration_config, "mssql_example.port"),
Expand Down
28 changes: 28 additions & 0 deletions tests/fixtures/mysql_fixtures.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from typing import Dict, Generator, List
from uuid import uuid4

Expand All @@ -23,6 +24,17 @@ def mysql_example_secrets():
return integration_secrets["mysql_example"]


@pytest.fixture(scope="function")
def google_cloud_mysql_secrets():
secrets = integration_secrets.get("google_cloud_mysql", {})
secrets["host"] = secrets.get("host") or os.environ.get("GOOGLE_CLOUD_MYSQL_TEST_HOST")
secrets["dbname"] = secrets.get("dbname") or os.environ.get("GOOGLE_CLOUD_MYSQL_TEST_DBNAME")
secrets["username"] = secrets.get("username") or os.environ.get("GOOGLE_CLOUD_MYSQL_TEST_USERNAME")
secrets["password"] = secrets.get("password") or os.environ.get("GOOGLE_CLOUD_MYSQL_TEST_PASSWORD")
secrets["port"] = secrets.get("port") or os.environ.get("GOOGLE_CLOUD_MYSQL_TEST_PORT")
return secrets


@pytest.fixture(scope="function")
def dataset_config_mysql(
connection_config: ConnectionConfig,
Expand Down Expand Up @@ -112,6 +124,22 @@ def connection_config_mysql(db: Session) -> Generator:
connection_config.delete(db)


@pytest.fixture(scope="function")
def connection_config_google_cloud_mysql(db: Session, google_cloud_mysql_secrets) -> Generator:
connection_config = ConnectionConfig.create(
db=db,
data={
"name": str(uuid4()),
"key": "my_google_cloud_mysql_db_1",
"connection_type": ConnectionType.google_cloud_mysql,
"access": AccessLevel.write,
"secrets": google_cloud_mysql_secrets,
},
)
yield connection_config
connection_config.delete(db)


@pytest.fixture(scope="function")
def mysql_integration_session_cls(connection_config_mysql):
example_postgres_uri = MySQLConnector(connection_config_mysql).build_uri()
Expand Down
7 changes: 7 additions & 0 deletions tests/ops/integration_test_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ password="mysql_pw"
db="mysql_example"
port=3306

[google_cloud_mysql]
server=""
user=""
password=""
db=""
port=""

[redshift]
host=""
port=""
Expand Down
Loading
Loading