namespace PulumiWebServer open System open System.Collections.Generic open System.IO open Newtonsoft.Json [] type Configuration = { /// Name of this server, as it will be known to Pulumi. /// This isn't e.g. a hostname or anything; it's the key on which Pulumi deduplicates /// different runs of this plan. Name : string /// Private key with which to talk to the server PrivateKey : PrivateKey /// Public key corresponding to the PrivateKey (default has ".pub" appended) PublicKeyOverride : PublicKey option /// Umbrella domain name for all services Domain : DomainName /// All cnames to be created in DNS Cnames : Map /// All subdomains which are not cnames; /// e.g. (WellKnownSubdomain.Www, "www") would indicate /// the `www.domain.name` address, in the counterfactual /// world where `Www` were implemented as a subdomain /// and not a cname Subdomains : Set /// Email address to use with ACME registration AcmeEmail : EmailAddress /// Username for the user account to be created on the server RemoteUsername : Username } member this.PublicKey = match this.PublicKeyOverride with | Some k -> k | None -> let (PrivateKey k) = this.PrivateKey Path.Combine (k.Directory.FullName, k.Name + ".pub") |> FileInfo |> PublicKey [] [] type SerialisedConfig = { [] Name : string /// Path to private key [] PrivateKey : string /// Path to public key [] PublicKey : string [] Domain : string [] Cnames : Dictionary [] Subdomains : string[] [] AcmeEmail : string [] RemoteUsername : string } static member Make (config : Configuration) = { SerialisedConfig.PrivateKey = let (PrivateKey p) = config.PrivateKey in p.FullName Name = config.Name PublicKey = match config.PublicKeyOverride with | None -> null | Some (PublicKey p) -> p.FullName Domain = config.Domain.ToString () Cnames = config.Cnames |> Map.toSeq |> Seq.map (fun (cname, target) -> KeyValuePair (cname.ToString (), WellKnownCnameTarget.Serialise target) ) |> Dictionary Subdomains = config.Subdomains |> Seq.map (fun sub -> sub.ToString ()) |> Seq.toArray AcmeEmail = config.AcmeEmail.ToString () RemoteUsername = config.RemoteUsername.ToString () } static member Deserialise (config : SerialisedConfig) : Configuration = { Configuration.PrivateKey = FileInfo config.PrivateKey |> PrivateKey Name = config.Name PublicKeyOverride = match config.PublicKey with | null -> None | key -> FileInfo key |> PublicKey |> Some Domain = config.Domain |> DomainName Cnames = config.Cnames |> Seq.map (fun (KeyValue (cname, target)) -> WellKnownCname.Parse cname, WellKnownCnameTarget.Deserialise target ) |> Map.ofSeq Subdomains = match config.Subdomains with | null -> Set.empty | subdomains -> subdomains |> Seq.map WellKnownSubdomain.Parse |> Set.ofSeq AcmeEmail = config.AcmeEmail |> EmailAddress RemoteUsername = config.RemoteUsername |> Username } [] module Configuration = let get (configFile : Stream) : Configuration = use reader = new StreamReader (configFile) JsonConvert.DeserializeObject (reader.ReadToEnd ()) |> SerialisedConfig.Deserialise