Skip to content

Commit f0f0e05

Browse files
committed
overhaul of analyzer connection info lookup
Now supports connection string or host/key pairs Now looks for config files with an expected structure
1 parent 7a752ba commit f0f0e05

7 files changed

Lines changed: 131 additions & 52 deletions

File tree

paket.dependencies

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ nuget Microsoft.NET.Test.Sdk 16.5.0
1616
nuget Microsoft.SourceLink.GitHub prerelease copy_local: true
1717
nuget Microsoft.NETFramework.ReferenceAssemblies copy_local: true
1818

19+
nuget FSharp.SystemTextJson 0.10.25
1920
// [ FAKE GROUP ]
2021
group Build
2122
storage none

paket.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ NUGET
4141
FSharp.Control.AsyncSeq (2.0.23)
4242
FSharp.Core (>= 3.1.2) - restriction: >= net45
4343
FSharp.Core (>= 4.3.2) - restriction: && (< net45) (>= netstandard2.0)
44+
FSharp.SystemTextJson (0.10.25)
45+
FSharp.Core (>= 4.7) - restriction: >= netstandard2.0
46+
System.Text.Json (>= 4.6) - restriction: && (< netcoreapp3.0) (>= netstandard2.0)
4447
McMaster.NETCore.Plugins (1.1) - restriction: >= netcoreapp2.0
4548
Microsoft.DotNet.PlatformAbstractions (>= 3.1) - restriction: >= netcoreapp2.0
4649
Microsoft.Extensions.DependencyModel (>= 3.1) - restriction: >= netcoreapp2.0

src/FSharp.CosmosDb.Analyzer/Analyzer.fs

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,42 @@ module CosmosDbAnalyzer
22

33
open FSharp.Analyzers.SDK
44
open FSharp.CosmosDb.Analyzer
5-
open System
6-
open Azure.Cosmos
75

86
[<Analyzer>]
97
let cosmosDbAnalyzer: Analyzer =
108
fun (context: Context) ->
11-
printfn "pwd: %s" Environment.CurrentDirectory
12-
139
let syntaxBlocks = CosmosCodeAnalysis.findOperations context
1410

15-
let host = Environment.GetEnvironmentVariable "FSHARP_COSMOS_HOST"
16-
if isNull host || String.IsNullOrWhiteSpace host then
11+
let connStr = ConnectionLookup.findConnectionString context.FileName
12+
13+
match connStr with
14+
| Some connStr ->
15+
match CosmosCodeAnalyzer.testConnection connStr with
16+
| Error msg ->
17+
[ for block in syntaxBlocks -> Messaging.error msg block.range ]
18+
| Success client ->
19+
syntaxBlocks
20+
|> List.collect (fun block ->
21+
match CosmosCodeAnalyzer.findDatabaseOperation block with
22+
| Some(dbId, range) ->
23+
CosmosCodeAnalyzer.analyzeDatabaseOperation dbId range client
24+
|> List.append
25+
(match CosmosCodeAnalyzer.findContainerOperation block with
26+
| Some(containerName, range) ->
27+
CosmosCodeAnalyzer.analyzeContainerNameOperation dbId containerName range client
28+
| None -> [])
29+
|> List.append
30+
(match CosmosCodeAnalyzer.findParameters block with
31+
| Some(parameters, range) -> CosmosCodeAnalyzer.analyzeParameters block parameters range
32+
| None -> [])
33+
34+
| None ->
35+
match CosmosCodeAnalyzer.findParameters block with
36+
| Some(parameters, range) -> CosmosCodeAnalyzer.analyzeParameters block parameters range
37+
| None -> [])
38+
|> List.distinctBy (fun msg -> msg.Range)
39+
| None ->
1740
[ for block in syntaxBlocks ->
1841
Messaging.warning
19-
"Host for Cosmos DB wasn't set. Ensure there's an environment varialbe named 'FSHARP_COSMOS_HOST'"
42+
"No connection string was found, ensure either the appropriate environment variables or appsettings.json is created"
2043
block.range ]
21-
else
22-
let key = Environment.GetEnvironmentVariable "FSHARP_COSMOS_KEY"
23-
if isNull key || String.IsNullOrWhiteSpace key then
24-
[ for block in syntaxBlocks ->
25-
Messaging.warning
26-
"Access key for Cosmos DB wasn't set. Ensure there's an environment varialbe named 'FSHARP_COSMOS_KEY'"
27-
block.range ]
28-
else
29-
match CosmosCodeAnalyzer.testConnection host key with
30-
| Error msg ->
31-
[ for block in syntaxBlocks -> Messaging.error msg block.range ]
32-
| Success client ->
33-
syntaxBlocks
34-
|> List.collect (fun block ->
35-
match CosmosCodeAnalyzer.findDatabaseOperation block with
36-
| Some(dbId, range) ->
37-
CosmosCodeAnalyzer.analyzeDatabaseOperation dbId range client
38-
|> List.append
39-
(match CosmosCodeAnalyzer.findContainerOperation block with
40-
| Some(containerName, range) ->
41-
CosmosCodeAnalyzer.analyzeContainerNameOperation dbId containerName range client
42-
| None -> [])
43-
|> List.append
44-
(match CosmosCodeAnalyzer.findParameters block with
45-
| Some(parameters, range) ->
46-
CosmosCodeAnalyzer.analyzeParameters block parameters range
47-
| None -> [])
48-
49-
| None ->
50-
match CosmosCodeAnalyzer.findParameters block with
51-
| Some(parameters, range) -> CosmosCodeAnalyzer.analyzeParameters block parameters range
52-
| None -> [])
53-
|> List.distinctBy (fun msg -> msg.Range)
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
module internal ConnectionLookup
2+
3+
open System
4+
open System.IO
5+
open System.Text.Json
6+
open System.Text.Json.Serialization
7+
8+
let private gev key =
9+
let var = Environment.GetEnvironmentVariable key
10+
if isNull var || String.IsNullOrWhiteSpace var
11+
then None
12+
else Some var
13+
14+
let private makeConnStr = sprintf "AccountEndpoint=%s;AccountKey=%s;"
15+
16+
let private stringHasValue str =
17+
printfn "checking %s" str
18+
let ret = not (isNull str || String.IsNullOrEmpty str)
19+
printfn "ret: %A" ret
20+
ret
21+
22+
let private findFromEnv() =
23+
let host = gev "FSHARP_COSMOS_HOST"
24+
let key = gev "FSHARP_COSMOS_KEY"
25+
let cs = gev "FSHARP_COSMOS_CONNSTR"
26+
27+
match host, key, cs with
28+
| (Some host, Some key, None) -> sprintf "AccountEndpoint=%s;AccountKey=%s;" host key |> Some
29+
| (None, None, cs) -> cs
30+
| _ -> None
31+
32+
let private possibleFileNames = [ "appsettings.json"; "appsettings.Development.json" ]
33+
34+
type AppSettings =
35+
{ CosmosConnection: {| Host: String option; Key: String option; ConnectionString: String option |} option }
36+
37+
let private findFromAppSettings relativeFile =
38+
let folders =
39+
[ Environment.CurrentDirectory
40+
((FileInfo(relativeFile)).Directory).FullName ]
41+
42+
let settingsFiles =
43+
possibleFileNames
44+
|> List.map (fun file -> folders |> List.map (fun folder -> Path.Combine(folder, file)))
45+
|> List.append
46+
(possibleFileNames
47+
|> List.map (fun file -> folders |> List.map (fun folder -> Path.Combine(folder, file.ToLower()))))
48+
|> List.collect id
49+
|> List.filter File.Exists
50+
51+
let options = JsonSerializerOptions()
52+
options.Converters.Add(JsonFSharpConverter())
53+
54+
let parsedConfig =
55+
settingsFiles
56+
|> List.map (fun file ->
57+
let contents = File.ReadAllText file
58+
JsonSerializer.Deserialize<AppSettings>(contents, options))
59+
|> List.filter (fun config ->
60+
match config.CosmosConnection with
61+
| Some cc ->
62+
match cc.ConnectionString, cc.Host, cc.Key with
63+
| (Some cs, None, None) when stringHasValue cs -> true
64+
| (Some cs, Some _, Some _) when stringHasValue cs -> true
65+
| (Some _, Some host, Some key) when stringHasValue host && stringHasValue key -> true
66+
| (None, Some host, Some key) when stringHasValue host && stringHasValue key -> true
67+
| (_, _, _) -> false
68+
| None -> false)
69+
|> List.tryHead
70+
71+
match parsedConfig with
72+
| None -> None
73+
| Some config ->
74+
match config.CosmosConnection with
75+
| Some cc ->
76+
match cc.ConnectionString, cc.Host, cc.Key with
77+
| (Some cs, None, None) when stringHasValue cs -> Some cs
78+
| (Some cs, Some _, Some _) when stringHasValue cs -> Some cs
79+
| (Some _, Some host, Some key) when stringHasValue host && stringHasValue key ->
80+
makeConnStr host key |> Some
81+
| (None, Some host, Some key) when stringHasValue host && stringHasValue key ->
82+
makeConnStr host key |> Some
83+
| (_, _, _) -> None
84+
| None -> None
85+
86+
let findConnectionString relativeFile =
87+
match findFromEnv() with
88+
| Some connStr -> Some connStr
89+
| None ->
90+
match findFromAppSettings relativeFile with
91+
| Some connStr -> Some connStr
92+
| None -> None

src/FSharp.CosmosDb.Analyzer/CosmosCodeAnalyzer.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ type ConnectionResult =
1313
| Success of CosmosClient
1414

1515
module CosmosCodeAnalyzer =
16-
let testConnection host key =
17-
let client = new CosmosClient(host, key, CosmosClientOptions())
16+
let testConnection connStr =
17+
let client = new CosmosClient(connStr, CosmosClientOptions())
1818

1919
try
2020
client.ReadAccountAsync()

src/FSharp.CosmosDb.Analyzer/FSharp.CosmosDb.Analyzer.fsproj

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFramework>netcoreapp2.0</TargetFramework>
4-
<PackageOutputPath>../../.nupkg</PackageOutputPath>
5-
<PackageLicenseExpression>MIT</PackageLicenseExpression>
6-
<RepositoryUrl>https://github.com/aaronpowell/FSharp.CosmosDb.git</RepositoryUrl>
7-
<RepositoryType>git</RepositoryType>
8-
<PublishRepositoryUrl>true</PublishRepositoryUrl>
9-
<Title>FSharp.CosmosDb.Analyzer</Title>
10-
<PackageDescription>FSharp.CosmosDb.Analyzer is an F# analyzer for the FSharp.CosmosDb package to help you write valid CosmosDb queries.</PackageDescription>
11-
<Authors>aaron.powell</Authors>
12-
<PackageReleaseNotes></PackageReleaseNotes>
134
</PropertyGroup>
145
<ItemGroup>
156
<Compile Include="Types.fs" />
@@ -18,6 +9,7 @@
189
<Compile Include="Messaging.fs" />
1910
<Compile Include="CosmosCodeAnalyzer.fs" />
2011
<Compile Include="CosmosCodeAnalysis.fs" />
12+
<Compile Include="ConnectionLookup.fs" />
2113
<Compile Include="Analyzer.fs" />
2214
</ItemGroup>
2315
<Import Project="..\..\.paket\Paket.Restore.targets" />

src/FSharp.CosmosDb.Analyzer/paket.references

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ FSharp.Core
22
FSharp.Analyzers.SDK
33
FSharp.Compiler.Service
44
Azure.Cosmos
5-
FSharp.Control.AsyncSeq
5+
FSharp.Control.AsyncSeq
6+
FSharp.SystemTextJson

0 commit comments

Comments
 (0)