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

     1  package gce
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/caos/orbos/mntr"
     9  
    10  	"github.com/caos/orbos/internal/operator/orbiter/kinds/providers/core"
    11  
    12  	"github.com/caos/orbos/internal/helpers"
    13  
    14  	"github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/dynamic"
    15  	"github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/dynamic/wrap"
    16  
    17  	"github.com/caos/orbos/internal/operator/common"
    18  	"github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra"
    19  	dynamiclbmodel "github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/dynamic"
    20  
    21  	"github.com/caos/orbos/internal/operator/orbiter"
    22  	//	externallbmodel "github.com/caos/orbos/internal/operator/orbiter/kinds/loadbalancers/external"
    23  )
    24  
    25  func query(
    26  	desired *Spec,
    27  	current *Current,
    28  	lb interface{},
    29  	svc *machinesService,
    30  	nodeAgentsCurrent *common.CurrentNodeAgents,
    31  	nodeAgentsDesired *common.DesiredNodeAgents,
    32  	naFuncs core.IterateNodeAgentFuncs,
    33  	orbiterCommit string,
    34  ) (ensureFunc orbiter.EnsureFunc, err error) {
    35  
    36  	lbCurrent, ok := lb.(*dynamiclbmodel.Current)
    37  	if !ok {
    38  		panic(fmt.Errorf("unknown or unsupported load balancing of type %T", lb))
    39  	}
    40  	vips, _, err := lbCurrent.Current.Spec(svc)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	normalized, firewalls := normalize(svc.context, vips)
    45  
    46  	var (
    47  		ensureLB             func() error
    48  		createFWs, deleteFWs []func() error
    49  	)
    50  	if err := helpers.Fanout([]func() error{
    51  		func() error {
    52  			var err error
    53  			ensureLB, err = queryLB(svc.context, normalized)
    54  			return err
    55  		},
    56  		func() error {
    57  			var err error
    58  			createFWs, deleteFWs, err = queryFirewall(svc.context, firewalls)
    59  			return err
    60  		},
    61  	})(); err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	current.Current.Ingresses = make(map[string]*infra.Address)
    66  	for _, lb := range normalized {
    67  		current.Current.Ingresses[lb.transport] = &infra.Address{
    68  			Location:     lb.address.gce.Address,
    69  			BackendPort:  internalPort(lb),
    70  			FrontendPort: externalPort(lb),
    71  		}
    72  	}
    73  
    74  	queryNA, installNA := naFuncs(nodeAgentsCurrent)
    75  
    76  	desireNodeAgent := func(pool string, machine infra.Machine) error {
    77  
    78  		machineID := machine.ID()
    79  		machineMonitor := svc.context.monitor.WithField("machine", machineID)
    80  		na, _ := nodeAgentsDesired.Get(machineID)
    81  		if na.Software.Health.Config == nil {
    82  			na.Software.Health.Config = make(map[string]string)
    83  		}
    84  
    85  		for _, lb := range normalized {
    86  			for _, destPool := range lb.targetPool.destPools {
    87  				if pool == destPool {
    88  					key := fmt.Sprintf(
    89  						"%s:%d%s",
    90  						"0.0.0.0",
    91  						lb.healthcheck.gce.Port,
    92  						lb.healthcheck.gce.RequestPath)
    93  
    94  					value := fmt.Sprintf(
    95  						"--protocol %s --ip %s --port %d --path %s --status %d --proxy=%t",
    96  						lb.healthcheck.desired.Protocol,
    97  						machine.IP(),
    98  						internalPort(lb),
    99  						lb.healthcheck.desired.Path,
   100  						lb.healthcheck.desired.Code,
   101  						lb.healthcheck.proxyProtocol,
   102  					)
   103  
   104  					if v := na.Software.Health.Config[key]; v != value {
   105  						na.Software.Health.Config[key] = value
   106  						machineMonitor.WithFields(map[string]interface{}{
   107  							"listen": key,
   108  							"checks": value,
   109  						}).Debug("Healthcheck desired")
   110  					}
   111  					fw := common.ToFirewall("external", map[string]*common.Allowed{
   112  						lb.healthcheck.gce.Description: {
   113  							Port:     fmt.Sprintf("%d", lb.healthcheck.gce.Port),
   114  							Protocol: "tcp",
   115  						},
   116  					})
   117  					if !na.Firewall.Contains(fw) {
   118  						machineMonitor.WithField("ports", fw.ToCurrent()).Debug("Firewall desired")
   119  					}
   120  					na.Firewall.Merge(fw)
   121  				}
   122  			}
   123  		}
   124  		running, err := queryNA(machine, orbiterCommit)
   125  		if err != nil {
   126  			return err
   127  		}
   128  		if !running {
   129  			return installNA(machine)
   130  		}
   131  
   132  		return nil
   133  	}
   134  
   135  	svc.onCreate = desireNodeAgent
   136  	wrappedMachines := wrap.MachinesService(svc, *lbCurrent, nil, func(vip *dynamic.VIP) string {
   137  		for _, transport := range vip.Transport {
   138  			address, ok := current.Current.Ingresses[transport.Name]
   139  			if ok {
   140  				return address.Location
   141  			}
   142  		}
   143  		panic(fmt.Errorf("external address for %v is not ensured", vip))
   144  	})
   145  	return func(pdf func(mntr.Monitor) error) *orbiter.EnsureResult {
   146  
   147  		var done bool
   148  		return orbiter.ToEnsureResult(done, helpers.Fanout([]func() error{
   149  			func() error { return ensureIdentityAwareProxyAPIEnabled(svc.context) },
   150  			func() error { return ensureNetwork(svc.context, createFWs, deleteFWs) },
   151  			svc.restartPreemptibleMachines,
   152  			ensureLB,
   153  			func() error {
   154  				pools, err := svc.ListPools()
   155  				if err != nil {
   156  					return err
   157  				}
   158  
   159  				var desireNodeAgents []func() error
   160  				for _, pool := range pools {
   161  					machines, listErr := svc.List(pool)
   162  					if listErr != nil {
   163  						err = helpers.Concat(err, listErr)
   164  					}
   165  					for _, machine := range machines {
   166  						desireNodeAgents = append(desireNodeAgents, func(p string, m infra.Machine) func() error {
   167  							return func() error {
   168  								return desireNodeAgent(p, m)
   169  							}
   170  						}(pool, machine))
   171  					}
   172  				}
   173  				return helpers.Fanout(desireNodeAgents)()
   174  			},
   175  			func() error {
   176  				var err error
   177  				lbDone, err := wrappedMachines.InitializeDesiredNodeAgents()
   178  				if err != nil {
   179  					return err
   180  				}
   181  
   182  				fwDone, err := core.DesireInternalOSFirewall(svc.context.monitor, nodeAgentsDesired, nodeAgentsCurrent, svc, false, []string{"eth0"})
   183  				if err != nil {
   184  					return err
   185  				}
   186  				done = lbDone && fwDone
   187  
   188  				return err
   189  			},
   190  		})())
   191  	}, initPools(current, desired, svc, normalized, wrappedMachines)
   192  }
   193  
   194  func internalPort(lb *normalizedLoadbalancer) uint16 {
   195  	return lb.backendPort
   196  }
   197  
   198  func externalPort(lb *normalizedLoadbalancer) uint16 {
   199  	port, err := strconv.ParseInt(strings.Split(lb.forwardingRule.gce.PortRange, "-")[0], 10, 16)
   200  	if err != nil {
   201  		panic(err)
   202  	}
   203  	return uint16(port)
   204  }