@@ -69,9 +69,19 @@ class MetabaseConfig(DatasetLineageProviderConfigBase, StatefulIngestionConfigBa
69
69
default = None ,
70
70
description = "optional URL to use in links (if `connect_uri` is only for ingestion)" ,
71
71
)
72
- username : Optional [str ] = Field (default = None , description = "Metabase username." )
72
+ username : Optional [str ] = Field (
73
+ default = None ,
74
+ description = "Metabase username, used when an API key is not provided." ,
75
+ )
73
76
password : Optional [pydantic .SecretStr ] = Field (
74
- default = None , description = "Metabase password."
77
+ default = None ,
78
+ description = "Metabase password, used when an API key is not provided." ,
79
+ )
80
+
81
+ # https://www.metabase.com/learn/metabase-basics/administration/administration-and-operation/metabase-api#example-get-request
82
+ api_key : Optional [pydantic .SecretStr ] = Field (
83
+ default = None ,
84
+ description = "Metabase API key. If provided, the username and password will be ignored. Recommended method." ,
75
85
)
76
86
# TODO: Check and remove this if no longer needed.
77
87
# Config database_alias is removed from sql sources.
@@ -178,30 +188,40 @@ def __init__(self, ctx: PipelineContext, config: MetabaseConfig):
178
188
self .source_config : MetabaseConfig = config
179
189
180
190
def setup_session (self ) -> None :
181
- login_response = requests .post (
182
- f"{ self .config .connect_uri } /api/session" ,
183
- None ,
184
- {
185
- "username" : self .config .username ,
186
- "password" : (
187
- self .config .password .get_secret_value ()
188
- if self .config .password
189
- else None
190
- ),
191
- },
192
- )
191
+ self .session = requests .session ()
192
+ if self .config .api_key :
193
+ self .session .headers .update (
194
+ {
195
+ "x-api-key" : self .config .api_key .get_secret_value (),
196
+ "Content-Type" : "application/json" ,
197
+ "Accept" : "*/*" ,
198
+ }
199
+ )
200
+ else :
201
+ # If no API key is provided, generate a session token using username and password.
202
+ login_response = requests .post (
203
+ f"{ self .config .connect_uri } /api/session" ,
204
+ None ,
205
+ {
206
+ "username" : self .config .username ,
207
+ "password" : (
208
+ self .config .password .get_secret_value ()
209
+ if self .config .password
210
+ else None
211
+ ),
212
+ },
213
+ )
193
214
194
- login_response .raise_for_status ()
195
- self .access_token = login_response .json ().get ("id" , "" )
215
+ login_response .raise_for_status ()
216
+ self .access_token = login_response .json ().get ("id" , "" )
196
217
197
- self .session = requests .session ()
198
- self .session .headers .update (
199
- {
200
- "X-Metabase-Session" : f"{ self .access_token } " ,
201
- "Content-Type" : "application/json" ,
202
- "Accept" : "*/*" ,
203
- }
204
- )
218
+ self .session .headers .update (
219
+ {
220
+ "X-Metabase-Session" : f"{ self .access_token } " ,
221
+ "Content-Type" : "application/json" ,
222
+ "Accept" : "*/*" ,
223
+ }
224
+ )
205
225
206
226
# Test the connection
207
227
try :
@@ -217,15 +237,17 @@ def setup_session(self) -> None:
217
237
)
218
238
219
239
def close (self ) -> None :
220
- response = requests .delete (
221
- f"{ self .config .connect_uri } /api/session" ,
222
- headers = {"X-Metabase-Session" : self .access_token },
223
- )
224
- if response .status_code not in (200 , 204 ):
225
- self .report .report_failure (
226
- title = "Unable to Log User Out" ,
227
- message = f"Unable to logout for user { self .config .username } " ,
240
+ # API key authentication does not require session closure.
241
+ if not self .config .api_key :
242
+ response = requests .delete (
243
+ f"{ self .config .connect_uri } /api/session" ,
244
+ headers = {"X-Metabase-Session" : self .access_token },
228
245
)
246
+ if response .status_code not in (200 , 204 ):
247
+ self .report .report_failure (
248
+ title = "Unable to Log User Out" ,
249
+ message = f"Unable to logout for user { self .config .username } " ,
250
+ )
229
251
super ().close ()
230
252
231
253
def emit_dashboard_mces (self ) -> Iterable [MetadataWorkUnit ]:
0 commit comments