github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/internal/operator/orbiter/kinds/providers/cs/ingress.go (about)

     1  package cs
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/caos/orbos/internal/operator/orbiter/kinds/providers/core"
     9  
    10  	"github.com/caos/orbos/mntr"
    11  
    12  	"github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra"
    13  	"github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/dynamic"
    14  	dynamiclbmodel "github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/dynamic"
    15  )
    16  
    17  func desiredToCurrentVIP(current *Current) func(vip *dynamiclbmodel.VIP) string {
    18  	return func(vip *dynamic.VIP) string {
    19  		for idx := range vip.Transport {
    20  			transport := vip.Transport[idx]
    21  			address, ok := current.Current.Ingresses[transport.Name]
    22  			if ok {
    23  				return address.Location
    24  			}
    25  		}
    26  		panic(fmt.Errorf("external address for %v is not ensured", vip))
    27  	}
    28  }
    29  
    30  func checkAuth(_ infra.Machine) (string, int) {
    31  	return `#!/bin/sh
    32  
    33  set -e
    34  
    35  curl -f -H "Authorization: Bearer $(cat /var/orbiter/cstoken)" "https://api.cloudscale.ch/v1/floating-ips"
    36  `, 0
    37  }
    38  
    39  func notifyMaster(hostPools map[string][]*dynamiclbmodel.VIP, current *Current, poolsWithUnassignedVIPs map[string]bool) func(m infra.Machine) (string, bool) {
    40  	return func(m infra.Machine) (string, bool) {
    41  
    42  		machine := m.(*machine)
    43  		return fmt.Sprintf(`#!/bin/sh
    44  
    45  set -e
    46  
    47  # API token (with write permission) to access the cloudscale.ch API.
    48  api_token="$(cat /var/orbiter/cstoken)"
    49  
    50  # Set of Floating IPs shared between the servers within the same VRRP group.
    51  floating_ipv4='%s'
    52  
    53  # UUID of the server that this script is running on.
    54  # The UUID of the server can be retrieved using the API.
    55  server_uuid='%s'
    56  
    57  # Call the cloudscale.ch API to assign a specific Floating IP to this server.
    58  set_master() {
    59  	curl \
    60  		-f \
    61  		-H "Authorization: Bearer $api_token" \
    62  		-F server="$server_uuid" \
    63  		"https://api.cloudscale.ch/v1/floating-ips/$1"
    64  }
    65  
    66  for VIP in "$floating_ipv4"; do
    67  		set_master $VIP
    68  done
    69  `, strings.Join(hostedVIPs(hostPools, m, current), " "), machine.server.UUID), poolsWithUnassignedVIPs[machine.poolName]
    70  	}
    71  }
    72  
    73  func allHostedVIPs(hostPools map[string][]*dynamiclbmodel.VIP, service core.MachinesService, current *Current) (map[string][]string, error) {
    74  	vips := make(map[string][]string, 0)
    75  	pools, err := service.ListPools()
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	for _, pool := range pools {
    80  		poolMachines, err := service.List(pool)
    81  		if err != nil {
    82  			return nil, err
    83  		}
    84  		for idx := range poolMachines {
    85  			machine := poolMachines[idx]
    86  			vips[machine.ID()] = hostedVIPs(hostPools, machine, current)
    87  		}
    88  	}
    89  	return vips, nil
    90  }
    91  
    92  func hostedVIPs(hostPools map[string][]*dynamiclbmodel.VIP, m infra.Machine, current *Current) []string {
    93  	seen := make(map[string]bool)
    94  	var locations []string
    95  	for hostPool, vips := range hostPools {
    96  		if m.(*machine).server.Tags["pool"] != hostPool {
    97  			continue
    98  		}
    99  		for vipIdx := range vips {
   100  			vip := vips[vipIdx]
   101  			for transpIdx := range vip.Transport {
   102  				transp := vip.Transport[transpIdx]
   103  				addr, ok := current.Current.Ingresses[transp.Name]
   104  				if !ok || addr == nil {
   105  					continue
   106  				}
   107  				if _, ok := seen[addr.Location]; !ok {
   108  					seen[addr.Location] = true
   109  					locations = append(locations, addr.Location)
   110  				}
   111  			}
   112  		}
   113  	}
   114  	return locations
   115  }
   116  
   117  func ensureTokens(monitor mntr.Monitor, token []byte, authCheckResult []dynamiclbmodel.AuthCheckResult) []func() error {
   118  	var ensure []func() error
   119  	for idx := range authCheckResult {
   120  		ensure = append(ensure, func(result dynamiclbmodel.AuthCheckResult) func() error {
   121  			return func() error { return ensureToken(monitor, token, result) }
   122  		}(authCheckResult[idx]))
   123  	}
   124  	return ensure
   125  }
   126  
   127  func ensureToken(monitor mntr.Monitor, token []byte, authCheckResult dynamiclbmodel.AuthCheckResult) error {
   128  	if authCheckResult.ExitCode != 0 {
   129  		if err := authCheckResult.Machine.WriteFile("/var/orbiter/cstoken", bytes.NewReader(token), 600); err != nil {
   130  			return err
   131  		}
   132  		monitor.WithField("machine", authCheckResult.Machine.ID()).Info("API token written")
   133  	}
   134  	return nil
   135  }