class qdii::vpn {
  # The encrypted network created by Wireguard.
  $wg_network = '192.168.2.0/24'
  $wg_network6 = '2a02:168:47b1:0:47a1:a412:1000:1/100'

  # An endpoint available over the internet to allow del.dodges.it to connect
  $ter_endpoint    = 'swip.dodges.it:51821'
  $muffin_endpoint = 'swip.dodges.it:51820'
  $rpi3_endpoint   = 'swip.dodges.it:51822'
  $del_endpoint    = 'del.dodges.it:51822'
  #$smb_endpoint    = 'swip.dodges.it:50109'
  $ovh_endpoint    = 'ovh.dodges.it:51820'
  $nas_endpoint    = 'swip.dodges.it:50108'
  $limo_endpoint   = 'swip.dodges.it:51823'

  # The private keys are automatically generated by puppet::wireguard and
  # stored in /etc/wireguard/$iface.
  $pubkeys = {
    del    => 'I1etAkZ+c5+NNZzH53UdBm3AD0UGYcP902K/n+L9Hwk=',
    limo   => 'LAZ2tcpi8qlIc/4DILBj57Je3PFv5ISg/fbxxGEgziM=',
    rpi3   => 'M1c93GS971NqFNdF7xZgLLOSbPK3wq07yr/9XG/Vkgo=',
    muffin => 'Ba+m31gyz7WJ21aiS+ALaWn5qbP9BZvhN3ydkHwrVmI=',
    smb    => 'LORYaSg62HnZk8m1/e73qKH5eT6E8NHYG4lVPmPsg3g=',
    qd4a   => 'cjTa2l3jCCB5HxjZoDykWHYqJDCpY2CLakmdMYaLiCg=',
    ter    => 'iV63+QYzp11sQjpqhoaR7dh37XSMYwg9yaSt7xNHcC8=',
    liwo   => 'bMeUFHzrR6+FtVg/rQD+NgRhPnogc8YfHDj4m2QvJ1s=',
    ovh    => '4Ilb61wSNyXyo/BzgeiWVhxXQGo+rGMDZKLmQSl5Gxw=',
    nas    => 'r/dmO/awlPSozd2CYX3n9yNFHEWPE4bhoVGVPFtXAGk=',
  }

  # Home subnetwork. This is used by puppet::wireguard to determine the
  # underlying interface by which the packets are transferred (I think).
  $homeips = {
    del    => '192.168.1.31',  # Careful this is part of Nicolas' subnetwork.
    limo   => '192.168.1.10',
    rpi3   => '192.168.1.12',
    smb    => '192.168.1.7',
    muffin => '192.168.1.15',
    qd4a   => '192.168.1.35',
    ter    => '192.168.1.20',
    liwo   => '192.168.1.23',
    ovh    => '192.168.1.11',
    nas    => '192.168.1.44',
  }

  # There is no DHCP with Wire, so the IP addresses are configured statically.
  $pubips = {
    del    => '192.168.2.31',
    limo   => '192.168.2.10',
    rpi3   => '192.168.2.12',
    smb    => '192.168.2.7',
    muffin => '192.168.2.15',
    qd4a   => '192.168.2.35',
    ter    => '192.168.2.20',
    liwo   => '192.168.2.23',
    ovh    => '192.168.2.11',
    nas    => '192.168.2.44',
  }

  # Part of the prefix assigned by Init7 to me.
  $pubip6s = {
    del    => '2a02:168:47b1:0:47a1:a412:1000:1',
    limo   => '2a02:168:47b1:0:47a1:a412:1000:10',
    rpi3   => '2a02:168:47b1:0:47a1:a412:1000:12',
    smb    => '2a02:168:47b1:0:47a1:a412:1000:7',
    muffin => '2a02:168:47b1:0:47a1:a412:1000:15',
    qd4a   => '2a02:168:47b1:0:47a1:a412:1000:35',
    ter    => '2a02:168:47b1:0:47a1:a412:1000:20',
    liwo   => '2a02:168:47b1:0:47a1:a412:1000:23',
    ovh    => '2a02:168:47b1:0:47a1:a412:1000:11',
    nas    => '2a02:168:47b1:0:47a1:a412:1000:44',
  }

  $ter_peer = {
    public_key           => $pubkeys['ter'],
    # AllowedIPs is used both as ACL and as a routing table, therefore we need
    # to be careful. If we pass 0.0.0.0/0, it means we accept packets coming
    # from any source IP, but it also means we will use this peer as default
    # gateway to route everything to. Here we don't want that.
    allowed_ips          => [
      # Accept packets from the server over the home LAN network.
      $homeips['ter'],
      # Route packets to other devices via the VPN endpoint in IPv4.
      $wg_network,
      # Route packets to other devices via the VPN endpoint in IPv6.
      $wg_network6,
    ],
    description          => 'ter',
    # This is the internet endpoint. As the IP is not dynamic, this may need
    # updates when restarting the router :(
    endpoint             => $ter_endpoint,
    # The KeepAlive parameter is necessary because del.dodges.it is behind
    # a NAT, so the server cannot reconnect to it if the TCP link is torn.
    persistent_keepalive => 60,
  }

  $ovh_peer = {
    public_key           => $pubkeys['ovh'],
    allowed_ips          => [$pubips['ovh'], $pubip6s['ovh']],
    description          => 'ovh',
    endpoint             => $ovh_endpoint,
    persistent_keepalive => 60,
  }

  $nas_peer = {
    public_key           => $pubkeys['nas'],
    allowed_ips          => [$pubips['nas'], $pubip6s['nas']],
    description          => 'nas',
    endpoint             => $nas_endpoint,
    persistent_keepalive => 60,
  }

  $muffin_peer = {
    public_key           => $pubkeys['muffin'],
    allowed_ips          => [$pubips['muffin'], $pubip6s['muffin']],
    description          => 'muffin',
    endpoint             => $muffin_endpoint,
    persistent_keepalive => 60,
  }

  $limo_peer = {
    public_key  => $pubkeys['limo'],
    allowed_ips => [$pubips['limo'], $pubip6s['limo']],
    description => 'limo',
  }

  $rpi3_peer = {
    public_key           => $pubkeys['rpi3'],
    allowed_ips          => [$pubips['rpi3'], $pubip6s['rpi3']],
    endpoint             => $rpi3_endpoint,
    persistent_keepalive => 60,
    description          => 'rpi3',
  }

  $del_peer = {
    public_key           => $pubkeys['del'],
    allowed_ips          => [$pubips['del'], $pubip6s['del']],
    endpoint             => $del_endpoint,
    persistent_keepalive => 60,
    description          => 'del',
  }

  $smb_peer = {
    public_key           => $pubkeys['smb'],
    allowed_ips          => [$pubips['smb'], $pubip6s['smb']],
    description          => 'smb',
    persistent_keepalive => 60,
    #endpoint             => $smb_endpoint,
  }

  $liwo_peer = {
    public_key  => $pubkeys['liwo'],
    allowed_ips => [$pubips['liwo'], $pubip6s['liwo']],
    description => 'liwo',
  }

  # My laptop.
  if $::fqdn == 'limo.dodges.it' {
    wireguard::interface {'wg10':
      description      => 'limo',
      manage_firewall  => false,
      dport            => 51820,
      source_addresses => [$homeips['limo']],
      public_key       => $pubkeys['limo'],
      addresses        => [{'Address' => "${pubips['limo']}/24"}, {'Address' => "${pubip6s['limo']}/100"}],
      peers            => [$liwo_peer, $ter_peer, $muffin_peer, $rpi3_peer, $del_peer, $ovh_peer, $nas_peer],
    }
    $wg_ip = $pubips['limo']
    $wg_ip6 = $pubip6s['limo']
  }

  if $::fqdn == 'muffin.dodges.it' {
    wireguard::interface {'wg15':
      description      => 'muffin',
      manage_firewall  => false,
      dport            => 51820,
      source_addresses => [$homeips['muffin']],
      public_key       => $pubkeys['muffin'],
      addresses        => [{'Address' => "${pubips['muffin']}/24"}, {'Address' => "${pubip6s['muffin']}/100"}],
      peers            => [$liwo_peer, $ter_peer, $limo_peer, $rpi3_peer, $del_peer, $smb_peer, $ovh_peer, $nas_peer],
    }
    $wg_ip = $pubips['muffin']
    $wg_ip6 = $pubip6s['muffin']
  }

  if $::fqdn == 'ovh.dodges.it' {
    wireguard::interface {'wg11':
      description      => 'muffin',
      manage_firewall  => false,
      dport            => 51820,
      source_addresses => [$homeips['ovh']],
      public_key       => $pubkeys['ovh'],
      addresses        => [{'Address' => "${pubips['ovh']}/24"}, {'Address' => "${pubip6s['ovh']}/100"}],
      peers            => [$liwo_peer, $ter_peer, $limo_peer, $rpi3_peer, $del_peer, $smb_peer, $muffin_peer, $nas_peer],
    }
    $wg_ip = $pubips['ovh']
    $wg_ip6 = $pubip6s['ovh']
  }

  if $::fqdn == 'rpi3.dodges.it' {
    wireguard::interface {'wg12':
      description      => 'rpi3',
      manage_firewall  => false,
      dport            => 51820,
      source_addresses => [$homeips['rpi3']],
      public_key       => $pubkeys['rpi3'],
      addresses        => [{'Address' => "${pubips['rpi3']}/24"}, {'Address' => "${pubip6s['rpi3']}/100"}],
      peers            => [$liwo_peer, $ter_peer, $muffin_peer, $del_peer, $limo_peer, $smb_peer, $ovh_peer, $nas_peer],
    }
    $wg_ip = $pubips['rpi3']
    $wg_ip6 = $pubip6s['rpi3']
  }

  if $::fqdn == 'del.dodges.it' {
    wireguard::interface {'wg31':
      description      => 'del',
      manage_firewall  => false,
      dport            => 51820,
      source_addresses => [$homeips['del']],
      public_key       => $pubkeys['del'],
      addresses        => [{'Address' => "${pubips['del']}/24"}, {'Address' => "${pubip6s['del']}/100"}],
      peers            => [$liwo_peer, $ter_peer, $muffin_peer, $rpi3_peer, $del_peer, $smb_peer, $limo_peer, $ovh_peer],
    }
    $wg_ip = $pubips['del']
    $wg_ip6 = $pubip6s['del']
  }

  if $::fqdn == 'ter.dodges.it' {
    wireguard::interface {'wg20':
      description      => 'ter',
      manage_firewall  => false,
      dport            => 51820,
      source_addresses => [$homeips['ter']],
      public_key       => $pubkeys['ter'],
      addresses        => [{'Address' => "${pubips['ter']}/24"}, {'Address' => "${pubip6s['ter']}/100"}],
      peers            => [
        $liwo_peer,
        $del_peer,
        $muffin_peer,
        $limo_peer,
        $rpi3_peer,
        $smb_peer,
        { # qd4a
          public_key  => $pubkeys['qd4a'],
          allowed_ips => [$pubips['qd4a'], $pubip6s['qd4a']],
          description => 'qd4a',
        },
        $ovh_peer,
        $nas_peer
      ],
    }
    $wg_ip = $pubips['ter']
    $wg_ip6 = $pubip6s['ter']
  }

  if $qdii::k8s {
    # Modify the kubeadm-flags to add --node-ip=<wireguard ip address> so that
    # the kubernetes clusters lays on top of the VPN mesh.
    file { 'kubeadm-flags-directory':
      path    => '/var/lib/kubelet',
      ensure  => directory,
      owner   => 0,
      group   => 0,
      mode    => "0700",
    }
    -> file { 'kubeadm-flags':
      path    => '/var/lib/kubelet/kubeadm-flags.env',
      ensure  => file,
      content => "KUBELET_KUBEADM_ARGS=\"--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --pod-infra-container-image=registry.k8s.io/pause:3.9 --authentication-token-webhook --authorization-mode=Webhook --cloud-provider=external --feature-gates=CloudDualStackNodeIPs=true --node-ip=$wg_ip,$wg_ip6\"",
      owner   => 0,
      group   => 0,
      mode    => "0644",
    }
  }
}
