1- using Azure . Identity ;
21using Bicep . Local . Extension . Host . Handlers ;
32using Microsoft . Azure . Databricks . Client ;
4- using System . Net . Http . Headers ;
5- using System . Text ;
3+ using Microsoft . Extensions . Logging ;
4+ using Bicep . Extension . Databricks . Services ;
5+ using System . Net . Http ;
66using System . Text . Json ;
77
88namespace Bicep . Extension . Databricks . Handlers ;
@@ -11,121 +11,30 @@ public abstract class BaseHandler<TResource, TIdentifiers> : TypedResourceHandle
1111 where TResource : class , TIdentifiers
1212 where TIdentifiers : class
1313{
14- private DatabricksClient ? _databricksClient ;
15- private readonly HttpClient _httpClient ;
14+ protected readonly ILogger _logger ;
15+ private readonly IDatabricksClientFactory _factory ;
1616
17- protected BaseHandler ( )
17+ protected BaseHandler ( IDatabricksClientFactory factory , ILogger logger )
1818 {
19- _httpClient = new HttpClient ( ) ;
19+ _factory = factory ;
20+ _logger = logger ;
2021 }
2122
22- private async Task < string > GetAccessTokenAsync ( CancellationToken cancellationToken )
23- {
24- var envToken = Environment . GetEnvironmentVariable ( "DATABRICKS_ACCESS_TOKEN" ) ;
25- if ( ! string . IsNullOrEmpty ( envToken ) )
26- {
27- Console . WriteLine ( "[TRACE] Using DATABRICKS_ACCESS_TOKEN from environment variable" ) ;
28- return envToken ;
29- }
30- else
31- {
32- Console . WriteLine ( "[TRACE] Getting token using DefaultAzureCredential" ) ;
33- var credential = new DefaultAzureCredential ( ) ;
34- var tokenResponse = await credential . GetTokenAsync (
35- new Azure . Core . TokenRequestContext ( [ "2ff814a6-3304-4ab8-85cb-cd0e6f879c1d/.default" ] ) ,
36- cancellationToken ) ;
37- return tokenResponse . Token ;
38- }
39- }
40-
41- private async Task < DatabricksClient > GetDatabricksClient ( ResourceRequest request , CancellationToken cancellationToken )
42- {
43- if ( _databricksClient != null )
44- {
45- return _databricksClient ;
46- }
47-
48- var accessToken = await GetAccessTokenAsync ( cancellationToken ) ;
23+ protected Task < DatabricksClient > GetClientAsync ( string workspaceUrl , CancellationToken ct , int ? timeoutSeconds = null )
24+ => _factory . GetClientAsync ( workspaceUrl , ct , timeoutSeconds ) ;
4925
50- var baseUrl = request . Config . WorkspaceUrl . TrimEnd ( '/' ) ;
51- Console . WriteLine ( $ "[TRACE] Creating DatabricksClient for workspace: { baseUrl } ") ;
52-
53- _databricksClient = DatabricksClient . CreateClient ( baseUrl , accessToken ) ;
54- return _databricksClient ;
55- }
56-
57- protected async Task < DatabricksClient > GetClientAsync ( ResourceRequest request , CancellationToken cancellationToken )
26+ protected async Task < T ? > CallDatabricksApiForResponse < T > ( string workspaceUrl , HttpMethod method , string relativePath , CancellationToken ct , object ? payload = null , int ? timeoutSeconds = null )
5827 {
59- return await GetDatabricksClient ( request , cancellationToken ) ;
60- }
61-
62- protected async Task < string > CallDatabricksApiForResponse (
63- ResourceRequest request ,
64- string apiPath ,
65- object requestBody ,
66- CancellationToken cancellationToken )
67- {
68- var accessToken = await GetAccessTokenAsync ( cancellationToken ) ;
69-
70- _httpClient . DefaultRequestHeaders . Authorization = new AuthenticationHeaderValue ( "Bearer" , accessToken ) ;
71-
72- var databricksUrl = request . Config . WorkspaceUrl . TrimEnd ( '/' ) ;
73- var endpoint = $ "{ databricksUrl } { apiPath } ";
74-
75- var json = JsonSerializer . Serialize ( requestBody , new JsonSerializerOptions
76- {
77- PropertyNamingPolicy = JsonNamingPolicy . CamelCase ,
78- DefaultIgnoreCondition = System . Text . Json . Serialization . JsonIgnoreCondition . WhenWritingNull
79- } ) ;
80-
81- var content = new StringContent ( json , Encoding . UTF8 , "application/json" ) ;
82-
83- HttpResponseMessage response ;
84- if ( string . IsNullOrEmpty ( json ) || json == "{}" )
85- {
86- // For GET requests or requests with empty body, use GET method
87- response = await _httpClient . GetAsync ( endpoint , cancellationToken ) ;
88- }
89- else
90- {
91- // For requests with payload, use POST method
92- response = await _httpClient . PostAsync ( endpoint , content , cancellationToken ) ;
93- }
94-
95- var responseContent = await response . Content . ReadAsStringAsync ( cancellationToken ) ;
96-
28+ var response = await ( _factory as IDatabricksClientFactory ) . CallApiAsync ( workspaceUrl , method , relativePath , ct , payload , timeoutSeconds ) ;
9729 if ( ! response . IsSuccessStatusCode )
9830 {
99- throw new InvalidOperationException ( $ "Failed to call Databricks API { apiPath } . Status: { response . StatusCode } , Error: { responseContent } ") ;
31+ var body = await response . Content . ReadAsStringAsync ( ct ) ;
32+ throw new InvalidOperationException ( $ "Databricks API call failed: { ( int ) response . StatusCode } { response . ReasonPhrase } Body={ body } ") ;
10033 }
101-
102- return responseContent ;
34+ if ( typeof ( T ) == typeof ( object ) || response . Content . Headers . ContentLength == 0 )
35+ return default ;
36+ var json = await response . Content . ReadAsStringAsync ( ct ) ;
37+ return JsonSerializer . Deserialize < T > ( json , new JsonSerializerOptions { PropertyNameCaseInsensitive = true } ) ;
10338 }
10439
105- protected async Task < ResourceResponse > CallDatabricksApi (
106- ResourceRequest request ,
107- string apiPath ,
108- object requestBody ,
109- CancellationToken cancellationToken )
110- {
111- // Call the API and get the response content
112- await CallDatabricksApiForResponse ( request , apiPath , requestBody , cancellationToken ) ;
113-
114- return GetResponse ( request ) ;
115- }
116-
117- protected ResourceResponse CreateResourceResponse < TDatabricksResult > (
118- TDatabricksResult databricksResult ,
119- string resourceType ,
120- Func < TDatabricksResult , TIdentifiers > createIdentifiers ,
121- Func < TDatabricksResult , TResource > createResource )
122- {
123- return new ResourceResponse
124- {
125- Type = resourceType ,
126- ApiVersion = "2.0" ,
127- Identifiers = createIdentifiers ( databricksResult ) ,
128- Properties = createResource ( databricksResult )
129- } ;
130- }
13140}
0 commit comments