Skip to content

Instantly share code, notes, and snippets.

@akhansari
Last active August 18, 2021 15:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akhansari/21d41730c5cbb04cb5465c2de1a19028 to your computer and use it in GitHub Desktop.
Save akhansari/21d41730c5cbb04cb5465c2de1a19028 to your computer and use it in GitHub Desktop.
Simple Consul KV client in F#
[<AutoOpen>]
module Helpers =
let rec (|NestedHttpRequestException|_|) (e: exn) =
match e with
| null -> None
| :? Net.Http.HttpRequestException as e -> Some e
| e -> (|NestedHttpRequestException|_|) e.InnerException
[<RequireQualifiedAccess>]
module ConsulKv =
open System.Net.Http
open System.Text.Json
open Microsoft.Extensions.Configuration
let url, token =
let root =
ConfigurationBuilder()
.SetBasePath(IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables()
.Build()
root.GetValue<string> "consul:url" |> Uri,
root.GetValue<string> "consul:token"
let newClient () =
let client = new HttpClient()
client.BaseAddress <- url
client.DefaultRequestHeaders.Add ("X-Consul-Token", token)
client
let get (client: HttpClient) (key: string) =
async {
try
let! resp = client.GetAsync $"/v1/kv/{key}?raw" |> Async.AwaitTask
if resp.IsSuccessStatusCode then
let! body = resp.Content.ReadAsStringAsync() |> Async.AwaitTask
return Some body
else
return None
with NestedHttpRequestException e ->
return failwithf $"Consul not available: {client.BaseAddress}: {e.Message}"
}
let getJson<'T> client key =
async {
let! res = get client key
return res |> Option.map JsonSerializer.Deserialize<'T>
}
let getStrings client key =
async {
let! res = getJson<JsonElement> client key
return
res |> Option.map (fun elm ->
elm.EnumerateObject()
|> Seq.choose (fun e ->
if e.Value.ValueKind = JsonValueKind.String
then Some (e.Name, e.Value.GetString())
else None)
|> Map)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment