97 lines
3.4 KiB
FSharp
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 ()
|