21
21
22
22
namespace Azure . Datafactory . Extensions . Functions
23
23
{
24
- public static partial class DataLakeHelpers
24
+ public partial class DataLakeFunctions
25
25
{
26
+ private readonly ILogger < DataLakeFunctions > _logger ;
27
+ private readonly DataLakeConfigFactory _configFactory ;
28
+ public DataLakeFunctions ( ILogger < DataLakeFunctions > logger , DataLakeConfigFactory configFactory )
29
+ {
30
+ _logger = logger ;
31
+ _configFactory = configFactory ;
32
+ }
33
+
34
+
35
+
26
36
[ FunctionName ( "DataLakeGetItems" ) ]
27
- public static async Task < IActionResult > DataLakeGetItems (
28
- [ HttpTrigger ( AuthorizationLevel . Function , "get" /*, "post"*/ , Route = null ) ] HttpRequest req ,
29
- ILogger log )
37
+ public async Task < IActionResult > DataLakeGetItems (
38
+ [ HttpTrigger ( AuthorizationLevel . Function , "get" /*, "post"*/ , Route = null ) ] HttpRequest req )
30
39
{
31
40
req . GetQueryParameterDictionary ( ) ;
32
41
33
42
var userAgentKey = req . Headers . Keys . FirstOrDefault ( k => k . ToLower ( ) == "user-agent" || k . ToLower ( ) == "useragent" ) ;
34
- log . LogInformation ( $ "C# HTTP trigger function processed a request [User Agent: { ( userAgentKey == null ? "Unknown" : req . Headers [ userAgentKey ] . ToString ( ) ) } ].") ;
43
+ _logger . LogInformation ( $ "C# HTTP trigger function processed a request [User Agent: { ( userAgentKey == null ? "Unknown" : req . Headers [ userAgentKey ] . ToString ( ) ) } ].") ;
35
44
36
45
try
37
46
{
38
- var settings = DataLakeGetItemsConfig . ParseFromRequestBody ( req , log ) ;
39
- if ( string . IsNullOrWhiteSpace ( settings . AccountUri ) )
40
- throw new ArgumentException ( $ "Account Uri '{ settings . AccountUri } ' not found. Check the URI is correct.") ;
47
+ var dataLakeConfig = _configFactory . GetDataLakeConfig ( req ) ;
48
+ var getItemsConfig = _configFactory . GetItemsConfig ( req ) ;
49
+
50
+ if ( string . IsNullOrWhiteSpace ( dataLakeConfig . AccountUri ) )
51
+ throw new ArgumentException ( $ "Account Uri '{ dataLakeConfig . AccountUri } ' not found. Check the URI is correct.") ;
41
52
42
- var client = DataLakeClientFactory . GetDataLakeClient ( settings , log ) ;
43
- return await GetItemsAsync ( client , settings , log ) ;
53
+ var clientFactory = new DataLakeClientFactory ( _logger ) ;
54
+ var client = clientFactory . GetDataLakeClient ( dataLakeConfig ) ;
55
+ return await GetItemsAsync ( client , dataLakeConfig , getItemsConfig , _logger ) ;
44
56
}
45
57
catch ( ArgumentException ex )
46
58
{
47
- log . LogError ( ex . Message ) ;
59
+ _logger . LogError ( ex . Message ) ;
48
60
return new BadRequestObjectResult ( ex . Message ) ;
49
61
}
50
62
catch ( Exception ex )
51
63
{
52
- log . LogError ( ex . ToString ( ) ) ;
64
+ _logger . LogError ( ex . ToString ( ) ) ;
53
65
return new BadRequestObjectResult ( "An error occurred, see the Azure Function logs for more details" ) ;
54
66
}
55
67
}
56
68
57
69
58
70
59
71
[ FunctionName ( "DataLakeCheckPathCase" ) ]
60
- public static async Task < IActionResult > DataLakeCheckPathCase (
61
- [ HttpTrigger ( AuthorizationLevel . Function , "get" , Route = null ) ] HttpRequest req ,
62
- ILogger log )
72
+ public async Task < IActionResult > DataLakeCheckPathCase (
73
+ [ HttpTrigger ( AuthorizationLevel . Function , "get" , Route = null ) ] HttpRequest req )
63
74
{
64
75
var userAgentKey = req . Headers . Keys . FirstOrDefault ( k => k . ToLower ( ) == "user-agent" || k . ToLower ( ) == "useragent" ) ;
65
- log . LogInformation ( $ "C# HTTP trigger function processed a request [User Agent: { ( userAgentKey == null ? "Unknown" : req . Headers [ userAgentKey ] . ToString ( ) ) } ].") ;
76
+ _logger . LogInformation ( $ "C# HTTP trigger function processed a request [User Agent: { ( userAgentKey == null ? "Unknown" : req . Headers [ userAgentKey ] . ToString ( ) ) } ].") ;
66
77
67
78
try
68
79
{
69
- var settings = DataLakeCheckPathCaseConfig . ParseFromRequestBody ( req , log ) ;
70
- if ( string . IsNullOrWhiteSpace ( settings . AccountUri ) )
71
- throw new ArgumentException ( $ "Account Uri '{ settings . AccountUri } ' not found. Check the URI is correct.") ;
80
+ var dataLakeConfig = _configFactory . GetDataLakeConfig ( req ) ;
81
+ var getItemsConfig = _configFactory . GetCheckPathCaseConfig ( req ) ;
82
+
83
+ if ( string . IsNullOrWhiteSpace ( dataLakeConfig . AccountUri ) )
84
+ throw new ArgumentException ( $ "Account Uri '{ dataLakeConfig . AccountUri } ' not found. Check the URI is correct.") ;
72
85
73
- var client = DataLakeClientFactory . GetDataLakeClient ( settings , log ) ;
86
+ var clientFactory = new DataLakeClientFactory ( _logger ) ;
87
+ var client = clientFactory . GetDataLakeClient ( dataLakeConfig ) ;
74
88
75
- var paramsJsonFragment = GetParamsJsonFragment ( settings ) ;
76
- var validatedPath = await CheckPathAsync ( client , settings . Path , true , log ) ;
89
+ var paramsJsonFragment = GetParamsJsonFragment ( dataLakeConfig , getItemsConfig ) ;
90
+ var validatedPath = await CheckPathAsync ( client , getItemsConfig . Path , true , _logger ) ;
77
91
78
92
// If multiple files match, the function will throw and the catch block will return a BadRequestObjectResult
79
93
// If the path could not be found as a directory, try for a file...
80
- validatedPath = validatedPath ?? await CheckPathAsync ( client , settings . Path , false , log ) ;
94
+ validatedPath = validatedPath ?? await CheckPathAsync ( client , getItemsConfig . Path , false , _logger ) ;
81
95
82
96
var resultJson = "{" +
83
97
$ "{ paramsJsonFragment } , \" validatedPath\" :\" { validatedPath } \" " +
84
98
"}" ;
85
99
86
100
return validatedPath != null ?
87
- ( IActionResult ) new OkObjectResult ( JObject . Parse ( resultJson ) ) :
88
- ( IActionResult ) new NotFoundObjectResult ( JObject . Parse ( resultJson ) ) ;
101
+ ( IActionResult ) new OkObjectResult ( JObject . Parse ( resultJson ) ) :
102
+ ( IActionResult ) new NotFoundObjectResult ( JObject . Parse ( resultJson ) ) ;
89
103
}
90
104
catch ( ArgumentException ex )
91
105
{
92
- log . LogError ( ex . Message ) ;
106
+ _logger . LogError ( ex . Message ) ;
93
107
return new BadRequestObjectResult ( ex . Message ) ;
94
108
}
95
109
catch ( Exception ex )
96
110
{
97
- log . LogError ( ex . ToString ( ) ) ;
111
+ _logger . LogError ( ex . ToString ( ) ) ;
98
112
return new BadRequestObjectResult ( "An error occurred, see the Azure Function logs for more details" ) ;
99
113
}
100
114
}
101
115
102
116
103
117
104
- private static string GetParamsJsonFragment ( DataLakeConfig settings )
105
- {
106
- return $ "\" debugInfo\" : { AssemblyHelpers . GetAssemblyVersionInfoJson ( ) } ," +
107
- $ "\" parameters\" : { JsonConvert . SerializeObject ( settings , Formatting . Indented , new JsonSerializerSettings { NullValueHandling = Newtonsoft . Json . NullValueHandling . Ignore } ) } ";
108
- }
109
118
110
119
111
- //private static DataLakeFileSystemClient GetDataLakeClient(DataLakeConfig settings, ILogger log)
112
- //{
113
- // // This works as long as the account accessing (managed identity or visual studio user) has both of the following IAM permissions on the storage account:
114
- // // - Reader
115
- // // - Storage Blob Data Reader
116
- // var credential = new DefaultAzureCredential();
117
- // log.LogInformation($"Using credential Type: {credential.GetType().Name}");
118
120
119
- // var client = new DataLakeFileSystemClient(new Uri(settings.BaseUrl), credential);
120
- // if (!client.Exists())
121
- // return null;
122
121
123
- // return client;
124
- //}
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+ private string GetParamsJsonFragment ( DataLakeConfig dataLakeConfig , object parameters )
138
+ {
139
+ return $ "\" debugInfo\" : { AssemblyHelpers . GetAssemblyVersionInfoJson ( ) } ," +
140
+ $ "\" storageContainerUrl\" : { dataLakeConfig . BaseUrl } ," +
141
+ parameters == null ?
142
+ string . Empty :
143
+ $ "\" parameters\" : { JsonConvert . SerializeObject ( parameters , Formatting . Indented , new JsonSerializerSettings { NullValueHandling = Newtonsoft . Json . NullValueHandling . Ignore } ) } ";
144
+ }
125
145
126
146
127
- private async static Task < string > CheckPathAsync ( DataLakeFileSystemClient client , string path , bool isDirectory , ILogger log )
147
+ private async Task < string > CheckPathAsync ( DataLakeFileSystemClient client , string path , bool isDirectory , ILogger log )
128
148
{
129
149
if ( path == null || path . Trim ( ) == "/" )
130
150
return null ;
@@ -175,7 +195,7 @@ private async static Task<string> CheckPathAsync(DataLakeFileSystemClient client
175
195
return files . FirstOrDefault ( ) ;
176
196
}
177
197
178
- private static IList < string > MatchPathItemsCaseInsensitive ( DataLakeFileSystemClient client , string basePath , string searchItem , bool isDirectory , ILogger log )
198
+ private IList < string > MatchPathItemsCaseInsensitive ( DataLakeFileSystemClient client , string basePath , string searchItem , bool isDirectory , ILogger log )
179
199
{
180
200
var paths = client . GetPaths ( basePath ) . ToList ( ) ;
181
201
return paths . Where ( p => p . IsDirectory == isDirectory && Path . GetFileName ( p . Name ) . Equals ( searchItem , StringComparison . CurrentCultureIgnoreCase ) )
@@ -185,35 +205,35 @@ private static IList<string> MatchPathItemsCaseInsensitive(DataLakeFileSystemCli
185
205
}
186
206
187
207
188
- private static async Task < IActionResult > GetItemsAsync ( DataLakeFileSystemClient client , DataLakeGetItemsConfig settings , ILogger log )
208
+ private async Task < IActionResult > GetItemsAsync ( DataLakeFileSystemClient client , DataLakeConfig dataLakeConfig , DataLakeGetItemsConfig getItemsConfig , ILogger log )
189
209
{
190
- var directory = settings . IgnoreDirectoryCase ?
191
- await CheckPathAsync ( client , settings . Directory , true , log ) :
192
- settings . Directory ;
210
+ var directory = getItemsConfig . IgnoreDirectoryCase ?
211
+ await CheckPathAsync ( client , getItemsConfig . Directory , true , log ) :
212
+ getItemsConfig . Directory ;
193
213
194
- var paramsJsonFragment = GetParamsJsonFragment ( settings ) ;
214
+ var paramsJsonFragment = GetParamsJsonFragment ( dataLakeConfig , getItemsConfig ) ;
195
215
196
216
if ( ! client . GetDirectoryClient ( directory ) . Exists ( ) )
197
217
return new BadRequestObjectResult ( JObject . Parse ( $ "{{ { paramsJsonFragment } , \" error\" : \" Directory '{ directory } could not be found'\" }}") ) ;
198
218
199
219
var paths = client
200
- . GetPaths ( path : directory ?? string . Empty , recursive : settings . Recursive )
220
+ . GetPaths ( path : directory ?? string . Empty , recursive : getItemsConfig . Recursive )
201
221
. Select ( p => new DataLakeFile
202
222
{
203
223
Name = Path . GetFileName ( p . Name ) ,
204
224
Directory = p . IsDirectory . GetValueOrDefault ( false ) ?
205
225
p . Name :
206
226
Path . GetDirectoryName ( p . Name ) . Replace ( Path . DirectorySeparatorChar , '/' ) ,
207
227
FullPath = p . Name ,
208
- Url = Url . Combine ( settings . BaseUrl , p . Name ) ,
228
+ Url = Url . Combine ( dataLakeConfig . BaseUrl , p . Name ) ,
209
229
IsDirectory = p . IsDirectory . GetValueOrDefault ( false ) ,
210
230
ContentLength = p . ContentLength . GetValueOrDefault ( 0 ) ,
211
231
LastModified = p . LastModified . ToUniversalTime ( ) . ToString ( "yyyy-MM-ddTHH:mm:ss.fffZ" )
212
232
} )
213
233
. ToList ( ) ;
214
234
215
235
// 1: Filter the results using dynamic LINQ
216
- foreach ( var filter in settings . Filters . Where ( f => f . IsValid ) )
236
+ foreach ( var filter in getItemsConfig . Filters . Where ( f => f . IsValid ) )
217
237
{
218
238
var dynamicLinqQuery = filter . GetDynamicLinqString ( ) ;
219
239
string dynamicLinqQueryValue = filter . GetDynamicLinqValue ( ) ;
@@ -222,29 +242,29 @@ await CheckPathAsync(client, settings.Directory, true, log) :
222
242
}
223
243
224
244
// 2: Sort the results
225
- if ( ! string . IsNullOrWhiteSpace ( settings . OrderByColumn ) )
245
+ if ( ! string . IsNullOrWhiteSpace ( getItemsConfig . OrderByColumn ) )
226
246
{
227
247
paths = paths . AsQueryable ( )
228
- . OrderBy ( settings . OrderByColumn + ( settings . OrderByDescending ? " descending" : string . Empty ) )
248
+ . OrderBy ( getItemsConfig . OrderByColumn + ( getItemsConfig . OrderByDescending ? " descending" : string . Empty ) )
229
249
. ToList ( ) ;
230
250
}
231
251
232
252
// 3: Do a top N if required
233
- if ( settings . Limit > 0 && settings . Limit < paths . Count )
234
- paths = paths . Take ( settings . Limit ) . ToList ( ) ;
253
+ if ( getItemsConfig . Limit > 0 && getItemsConfig . Limit < paths . Count )
254
+ paths = paths . Take ( getItemsConfig . Limit ) . ToList ( ) ;
235
255
236
256
237
257
238
258
// Output the results
239
259
var versionAttribute = Attribute . GetCustomAttribute ( Assembly . GetExecutingAssembly ( ) , typeof ( AssemblyInformationalVersionAttribute ) ) as AssemblyInformationalVersionAttribute ;
240
260
241
- var IsEveryFilterValid = settings . Filters . All ( f => f . IsValid ) ;
261
+ var IsEveryFilterValid = getItemsConfig . Filters . All ( f => f . IsValid ) ;
242
262
var filesListJson = IsEveryFilterValid ?
243
263
$ "\" fileCount\" : { paths . Count } ," +
244
264
$ "\" files\" : { JsonConvert . SerializeObject ( paths , Formatting . Indented ) } " :
245
265
string . Empty ;
246
266
247
- var resultJson = $ "{{ { paramsJsonFragment } , { ( settings . IgnoreDirectoryCase && directory != settings . Directory ? $ "\" correctedFilePath\" : \" { directory } \" ," : string . Empty ) } { filesListJson } }}";
267
+ var resultJson = $ "{{ { paramsJsonFragment } , { ( getItemsConfig . IgnoreDirectoryCase && directory != getItemsConfig . Directory ? $ "\" correctedFilePath\" : \" { directory } \" ," : string . Empty ) } { filesListJson } }}";
248
268
249
269
return IsEveryFilterValid ?
250
270
( IActionResult ) new OkObjectResult ( JObject . Parse ( resultJson ) ) :
0 commit comments