@@ -84,13 +84,17 @@ def from_instance(
8484 region : str ,
8585 instance : str ,
8686 database : str ,
87+ user : Optional [str ] = None ,
88+ password : Optional [str ] = None ,
8789 ) -> MySQLEngine :
8890 """Create an instance of MySQLEngine from Cloud SQL instance
8991 details.
9092
9193 This method uses the Cloud SQL Python Connector to connect to Cloud SQL
9294 using automatic IAM database authentication with the Google ADC
93- credentials sourced from the environment.
95+ credentials sourced from the environment by default. If user and
96+ password arguments are given, basic database authentication will be
97+ used for database login.
9498
9599 More details can be found at https://github.com/GoogleCloudPlatform/cloud-sql-python-connector#credentials
96100
@@ -101,42 +105,74 @@ def from_instance(
101105 instance (str): The name of the Cloud SQL instance.
102106 database (str): The name of the database to connect to on the
103107 Cloud SQL instance.
108+ user (str, optional): Database user to use for basic database
109+ authentication and login. Defaults to None.
110+ password (str, optional): Database password for 'user' to use for
111+ basic database authentication and login. Defaults to None.
104112
105113 Returns:
106114 (MySQLEngine): The engine configured to connect to a
107115 Cloud SQL instance database.
108116 """
117+ # error if only one of user or password is set, must be both or neither
118+ if bool (user ) ^ bool (password ):
119+ raise ValueError (
120+ "Only one of 'user' or 'password' were specified. Either "
121+ "both should be specified to use basic user/password "
122+ "authentication or neither for IAM DB authentication."
123+ )
109124 engine = cls ._create_connector_engine (
110125 instance_connection_name = f"{ project_id } :{ region } :{ instance } " ,
111126 database = database ,
127+ user = user ,
128+ password = password ,
112129 )
113130 return cls (engine = engine )
114131
115132 @classmethod
116133 def _create_connector_engine (
117- cls , instance_connection_name : str , database : str
134+ cls ,
135+ instance_connection_name : str ,
136+ database : str ,
137+ user : Optional [str ],
138+ password : Optional [str ],
118139 ) -> sqlalchemy .engine .Engine :
119140 """Create a SQLAlchemy engine using the Cloud SQL Python Connector.
120141
121142 Defaults to use "pymysql" driver and to connect using automatic IAM
122143 database authentication with the IAM principal associated with the
123- environment's Google Application Default Credentials.
144+ environment's Google Application Default Credentials. If user and
145+ password arguments are given, basic database authentication will be
146+ used for database login.
124147
125148 Args:
126149 instance_connection_name (str): The instance connection
127150 name of the Cloud SQL instance to establish a connection to.
128151 (ex. "project-id:instance-region:instance-name")
129152 database (str): The name of the database to connect to on the
130153 Cloud SQL instance.
154+ user (str, optional): Database user to use for basic database
155+ authentication and login. Defaults to None.
156+ password (str, optional): Database password for 'user' to use for
157+ basic database authentication and login. Defaults to None.
158+
131159 Returns:
132160 (sqlalchemy.engine.Engine): Engine configured using the Cloud SQL
133161 Python Connector.
134162 """
135- # get application default credentials
136- credentials , _ = google .auth .default (
137- scopes = ["https://www.googleapis.com/auth/userinfo.email" ]
138- )
139- iam_database_user = _get_iam_principal_email (credentials )
163+ # if user and password are given, use basic auth
164+ if user and password :
165+ enable_iam_auth = False
166+ db_user = user
167+ # otherwise use automatic IAM database authentication
168+ else :
169+ # get application default credentials
170+ credentials , _ = google .auth .default (
171+ scopes = ["https://www.googleapis.com/auth/userinfo.email" ]
172+ )
173+ db_user = _get_iam_principal_email (credentials )
174+ enable_iam_auth = True
175+
140176 if cls ._connector is None :
141177 cls ._connector = Connector ()
142178
@@ -145,9 +181,10 @@ def getconn() -> pymysql.Connection:
145181 conn = cls ._connector .connect ( # type: ignore
146182 instance_connection_name ,
147183 "pymysql" ,
148- user = iam_database_user ,
184+ user = db_user ,
185+ password = password ,
149186 db = database ,
150- enable_iam_auth = True ,
187+ enable_iam_auth = enable_iam_auth ,
151188 )
152189 return conn
153190
0 commit comments