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

     1  package cs
     2  
     3  import (
     4  	"net/http"
     5  	"strconv"
     6  
     7  	"github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra"
     8  
     9  	"github.com/cloudscale-ch/cloudscale-go-sdk"
    10  
    11  	"github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/dynamic"
    12  )
    13  
    14  func queryFloatingIPs(context *context, loadbalancing map[string][]*dynamic.VIP, writeTo *Current) ([]func() error, []func() error, map[string]bool, error) {
    15  
    16  	haveUnassignedVIPs := make(map[string]bool)
    17  	floatingIPs, err := context.client.FloatingIPs.List(context.ctx, func(r *http.Request) {
    18  		params := r.URL.Query()
    19  		params["orb"] = []string{context.orbID}
    20  		params["provider"] = []string{context.providerID}
    21  	})
    22  	if err != nil {
    23  		return nil, nil, nil, err
    24  	}
    25  
    26  	var ensure []func() error
    27  createLoop:
    28  	for hostPool, vips := range loadbalancing {
    29  		for vipIdx := range vips {
    30  			vip := vips[vipIdx]
    31  			alreadyExists := false
    32  			for transportIdx := range vip.Transport {
    33  				transport := vip.Transport[transportIdx]
    34  				initCurrent(writeTo, transport)
    35  
    36  				for floatingIPIdx := range floatingIPs {
    37  					floatingIP := floatingIPs[floatingIPIdx]
    38  					if ensureCurrentIngress(floatingIP, hostPool, vipIdx, writeTo, transport) {
    39  						alreadyExists = true
    40  						if floatingIP.Server == nil || floatingIP.Server.UUID == "" {
    41  							haveUnassignedVIPs[hostPool] = true
    42  						}
    43  					}
    44  				}
    45  			}
    46  			if alreadyExists {
    47  				continue createLoop
    48  			}
    49  			ensure = append(ensure, func(hostPool string, vipIdx int) func() error {
    50  				return func() error {
    51  					_, err := context.client.FloatingIPs.Create(context.ctx, &cloudscale.FloatingIPCreateRequest{
    52  						RegionalResourceRequest: cloudscale.RegionalResourceRequest{},
    53  						TaggedResourceRequest: cloudscale.TaggedResourceRequest{Tags: map[string]string{
    54  							"orb":      context.orbID,
    55  							"provider": context.providerID,
    56  							"pool":     hostPool,
    57  							"idx":      strconv.Itoa(vipIdx),
    58  						}},
    59  						IPVersion:      4,
    60  						Server:         "",
    61  						Type:           "regional",
    62  						PrefixLength:   0,
    63  						ReversePointer: "",
    64  					})
    65  					if err != nil {
    66  						return err
    67  					}
    68  					return nil
    69  				}
    70  			}(hostPool, vipIdx))
    71  		}
    72  	}
    73  
    74  	var remove []func() error
    75  
    76  removeLoop:
    77  	for floatingIPIdx := range floatingIPs {
    78  		floatingIP := floatingIPs[floatingIPIdx]
    79  		matches := false
    80  		for hostPool, vips := range loadbalancing {
    81  			for vipIdx := range vips {
    82  				vip := vips[vipIdx]
    83  				for transpIdx := range vip.Transport {
    84  					transport := vip.Transport[transpIdx]
    85  					initCurrent(writeTo, transport)
    86  					matches = ensureCurrentIngress(floatingIP, hostPool, vipIdx, writeTo, transport) || matches
    87  				}
    88  			}
    89  		}
    90  		if matches {
    91  			continue removeLoop
    92  		}
    93  		remove = append(remove, func(ip string) func() error {
    94  			return func() error {
    95  				return context.client.FloatingIPs.Delete(context.ctx, ip)
    96  			}
    97  		}(floatingIP.IP()))
    98  	}
    99  	return ensure, remove, haveUnassignedVIPs, nil
   100  }
   101  
   102  func initCurrent(writeTo *Current, transport *dynamic.Transport) {
   103  	if writeTo.Current.Ingresses == nil {
   104  		writeTo.Current.Ingresses = make(map[string]*infra.Address)
   105  	}
   106  	if writeTo.Current.Ingresses[transport.Name] == nil {
   107  		writeTo.Current.Ingresses[transport.Name] = &infra.Address{}
   108  	}
   109  }
   110  
   111  func ensureCurrentIngress(floatingIP cloudscale.FloatingIP, hostPool string, vipIdx int, writeTo *Current, transport *dynamic.Transport) bool {
   112  	matches := false
   113  	if floatingIP.Tags["pool"] == hostPool && floatingIP.Tags["idx"] == strconv.Itoa(vipIdx) {
   114  		matches = true
   115  		writeTo.Current.Ingresses[transport.Name].Location = floatingIP.IP()
   116  		writeTo.Current.Ingresses[transport.Name].FrontendPort = uint16(transport.FrontendPort)
   117  		writeTo.Current.Ingresses[transport.Name].BackendPort = uint16(transport.BackendPort)
   118  	}
   119  	return matches
   120  }