quorate/services/bot-redirect/run.fsx

97 lines
3.4 KiB
FSharp

#load "bots.fsx"
open System
open System.IO
open System.Net.Http
open System.Net.Http.Headers
open System.Text
open System.Text.Json
open Bots
[<TailCall>]
let rec pages fetch offset collected =
let page: JsonElement =
fetch $"bots?botVerificationStatus=VERIFIED&limit=100&offset={offset}"
let slugs =
page.GetProperty("bots").EnumerateArray()
|> Seq.map (fun bot -> bot.GetProperty("slug").GetString())
|> Seq.toList
if slugs.Length = 100 then
pages fetch (offset + slugs.Length) (slugs :: collected)
else
slugs :: collected |> List.rev |> List.concat
let run () =
use settings =
JsonDocument.Parse(File.ReadAllText(Path.Combine(__SOURCE_DIRECTORY__, "settings.json")))
let config = settings.RootElement
let excluded = strings config "excluded" |> Set.ofList
use radar = new HttpClient()
radar.BaseAddress <- Uri(config.GetProperty("radar").GetString())
radar.DefaultRequestHeaders.Authorization <-
AuthenticationHeaderValue("Bearer", File.ReadAllText("/radar/token").Trim())
let fetch (path: string) =
use request = new HttpRequestMessage(HttpMethod.Get, path)
use response = radar.Send request
response.EnsureSuccessStatusCode() |> ignore
use body = JsonDocument.Parse(response.Content.ReadAsStream())
if not (body.RootElement.GetProperty("success").GetBoolean()) then
failwith $"Radar request failed: {path}"
body.RootElement.GetProperty("result").Clone()
let bots =
pages fetch 0 []
|> List.map (fun slug -> (fetch ("bots/" + slug)).GetProperty("bot") |> decode)
let desired = bots |> List.collect (headers excluded) |> routes config
let ns = config.GetProperty("namespace").GetString()
let endpoint = $"/apis/gateway.networking.k8s.io/v1/namespaces/{ns}/httproutes"
use kube = new HttpClient()
kube.BaseAddress <- Uri "https://kubernetes.default.svc"
kube.DefaultRequestHeaders.Authorization <-
AuthenticationHeaderValue(
"Bearer",
File.ReadAllText("/var/run/secrets/kubernetes.io/serviceaccount/token").Trim()
)
let send method (path: string) payload =
use request = new HttpRequestMessage(method, path)
payload
|> Option.iter (fun value ->
request.Content <- new StringContent(value, Encoding.UTF8, "application/apply-patch+yaml"))
use response = kube.Send request
response.EnsureSuccessStatusCode() |> ignore
use body = JsonDocument.Parse(response.Content.ReadAsStream())
body.RootElement.Clone()
let names = desired |> List.map (fun route -> route.metadata.name) |> Set.ofList
desired
|> List.iter (fun route ->
send
HttpMethod.Patch
(endpoint + "/" + route.metadata.name + "?fieldManager=bot-redirect")
(Some(JsonSerializer.Serialize route))
|> ignore)
let existing =
send HttpMethod.Get (endpoint + "?labelSelector=app.kubernetes.io%2Fmanaged-by%3Dbot-redirect") None
existing.GetProperty("items").EnumerateArray()
|> Seq.map (fun route -> route.GetProperty("metadata").GetProperty("name").GetString())
|> Seq.filter (fun name -> not (Set.contains name names))
|> Seq.iter (fun name -> send HttpMethod.Delete (endpoint + "/" + name) None |> ignore)
printfn "bots=%d routes=%d" bots.Length desired.Length
run ()