ce7cb702218693d08ea6d83464d2457c9250027c
This commit is contained in:
commit
34c5f8963c
1 changed files with 145336 additions and 0 deletions
93
services/mirrored-image/k8s/bootstrap/bootstrap-lib.fsx
Normal file
93
services/mirrored-image/k8s/bootstrap/bootstrap-lib.fsx
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
module Bootstrap
|
||||
|
||||
open System
|
||||
|
||||
type App =
|
||||
{ Name: string
|
||||
User: string
|
||||
Org: string
|
||||
Scopes: string list
|
||||
Client: string }
|
||||
|
||||
type Session = { User: string; State: obj }
|
||||
|
||||
type Store =
|
||||
{ Read: string -> Map<string, string>
|
||||
Write: string -> Map<string, string> -> unit }
|
||||
|
||||
type Quay =
|
||||
{ LoginAuth: unit -> string
|
||||
Login: string -> string -> string -> Session
|
||||
Access: string -> App -> unit
|
||||
Application: string -> App -> string
|
||||
Assign: string -> Session -> App -> unit
|
||||
Issue: Session -> App -> string }
|
||||
|
||||
type Config = { AdminPath: string }
|
||||
|
||||
let apps =
|
||||
[ { Name = "candidates-reader"
|
||||
User = "candidates-bot"
|
||||
Org = "candidates"
|
||||
Scopes = [ "repo:read" ]
|
||||
Client = "" }
|
||||
{ Name = "candidates-writer"
|
||||
User = "candidates-bot"
|
||||
Org = "candidates"
|
||||
Scopes = [ "repo:create"; "repo:write" ]
|
||||
Client = "" }
|
||||
{ Name = "mirror-reader"
|
||||
User = "mirror-bot"
|
||||
Org = "mirror"
|
||||
Scopes = [ "repo:read" ]
|
||||
Client = "" }
|
||||
{ Name = "mirror-writer"
|
||||
User = "mirror-bot"
|
||||
Org = "mirror"
|
||||
Scopes = [ "repo:create"; "repo:write" ]
|
||||
Client = "" } ]
|
||||
|
||||
let personaPath user = $"secret/data/quay/personas/{user}"
|
||||
let tokenPath app = $"secret/data/quay/oauth/{app.Name}"
|
||||
|
||||
let private field name (values: Map<string, string>) =
|
||||
match Map.tryFind name values with
|
||||
| Some value when not (String.IsNullOrWhiteSpace value) && value <> "PLACEHOLDER" -> value
|
||||
| _ -> invalidOp "credential is absent"
|
||||
|
||||
let run config store quay =
|
||||
let pending =
|
||||
apps
|
||||
|> List.filter (fun app ->
|
||||
let values = store.Read(tokenPath app)
|
||||
|
||||
match Map.tryFind "token" values with
|
||||
| Some value when not (String.IsNullOrWhiteSpace value) && value <> "PLACEHOLDER" -> false
|
||||
| _ -> true)
|
||||
|
||||
if not pending.IsEmpty then
|
||||
let admin = store.Read config.AdminPath |> field "token"
|
||||
|
||||
let loginAuth = quay.LoginAuth()
|
||||
|
||||
let sessions =
|
||||
pending
|
||||
|> List.map _.User
|
||||
|> List.distinct
|
||||
|> List.map (fun user ->
|
||||
let password = store.Read(personaPath user) |> field "password"
|
||||
let session = quay.Login user password loginAuth
|
||||
|
||||
let app = pending |> List.find (fun app -> app.User = user)
|
||||
|
||||
quay.Access admin app
|
||||
user, session)
|
||||
|> Map.ofList
|
||||
|
||||
for definition in pending do
|
||||
let client = quay.Application admin definition
|
||||
let app = { definition with Client = client }
|
||||
let session = sessions[app.User]
|
||||
quay.Assign admin session app
|
||||
let token = quay.Issue session app
|
||||
store.Write (tokenPath app) (Map.ofList (List.singleton ("token", token)))
|
||||
Loading…
Reference in a new issue