github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/internal/operator/orbiter/kinds/clusters/kubernetes/adapt.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"fmt"
     5  
     6  	core "k8s.io/api/core/v1"
     7  
     8  	"github.com/caos/orbos/internal/operator/common"
     9  	"github.com/caos/orbos/internal/operator/orbiter"
    10  	"github.com/caos/orbos/internal/operator/orbiter/kinds/clusters/core/infra"
    11  	"github.com/caos/orbos/mntr"
    12  	"github.com/caos/orbos/pkg/git"
    13  	"github.com/caos/orbos/pkg/kubernetes"
    14  	"github.com/caos/orbos/pkg/labels"
    15  	"github.com/caos/orbos/pkg/secret"
    16  	"github.com/caos/orbos/pkg/tree"
    17  )
    18  
    19  var deployErrors int
    20  
    21  func AdaptFunc(
    22  	apiLabels *labels.API,
    23  	clusterID string,
    24  	oneoff bool,
    25  	deployOrbiter bool,
    26  	pprof bool,
    27  	destroyProviders func(map[string]interface{}) (map[string]interface{}, error),
    28  	whitelist func(whitelist []*orbiter.CIDR),
    29  	gitClient *git.Client,
    30  ) orbiter.AdaptFunc {
    31  
    32  	return func(
    33  		monitor mntr.Monitor,
    34  		finishedChan chan struct{},
    35  		desiredTree *tree.Tree,
    36  		currentTree *tree.Tree,
    37  	) (
    38  		queryFunc orbiter.QueryFunc,
    39  		destroyFunc orbiter.DestroyFunc,
    40  		configureFunc orbiter.ConfigureFunc,
    41  		migrate bool,
    42  		secrets map[string]*secret.Secret,
    43  		err error,
    44  	) {
    45  		defer func() {
    46  			if err != nil {
    47  				err = fmt.Errorf("building %s failed: %w", desiredTree.Common.Kind, err)
    48  			}
    49  		}()
    50  
    51  		if desiredTree.Common.Version() != "v0" {
    52  			migrate = true
    53  		}
    54  
    55  		desiredKind, err := parseDesiredV0(desiredTree)
    56  		if err != nil {
    57  			return nil, nil, nil, migrate, nil, fmt.Errorf("parsing desired state failed: %w", err)
    58  		}
    59  		desiredTree.Parsed = desiredKind
    60  
    61  		if desiredKind.Spec.ControlPlane.Taints == nil {
    62  			taints := Taints([]Taint{{
    63  				Key:    "node-role.kubernetes.io/master",
    64  				Effect: core.TaintEffectNoSchedule,
    65  			}})
    66  			desiredKind.Spec.ControlPlane.Taints = &taints
    67  			migrate = true
    68  		}
    69  
    70  		for _, workers := range desiredKind.Spec.Workers {
    71  			if workers.Taints == nil {
    72  				taints := Taints(make([]Taint, 0))
    73  				workers.Taints = &taints
    74  				migrate = true
    75  			}
    76  		}
    77  
    78  		if err := desiredKind.validate(); err != nil {
    79  			return nil, nil, nil, migrate, nil, err
    80  		}
    81  
    82  		if desiredKind.Spec.Verbose && !monitor.IsVerbose() {
    83  			monitor = monitor.Verbose()
    84  		}
    85  
    86  		whitelist([]*orbiter.CIDR{&desiredKind.Spec.Networking.PodCidr})
    87  
    88  		k8sClient := tryToConnect(monitor, *desiredKind)
    89  
    90  		if k8sClient != nil && deployOrbiter {
    91  			if err := kubernetes.EnsureCaosSystemNamespace(monitor, k8sClient); err != nil {
    92  				deployErrors++
    93  				monitor.WithFields(map[string]interface{}{
    94  					"count": deployErrors,
    95  					"error": err.Error(),
    96  				}).Info("Applying Common failed, awaiting next iteration")
    97  			}
    98  			if deployErrors > 50 {
    99  				panic(err)
   100  			}
   101  
   102  			imageRegistry := desiredKind.Spec.CustomImageRegistry
   103  			if imageRegistry == "" {
   104  				imageRegistry = "ghcr.io"
   105  			}
   106  
   107  			if err := kubernetes.EnsureOrbiterArtifacts(
   108  				monitor,
   109  				apiLabels,
   110  				k8sClient,
   111  				pprof,
   112  				desiredKind.Spec.Versions.Orbiter,
   113  				imageRegistry,
   114  			); err != nil {
   115  				deployErrors++
   116  				monitor.WithFields(map[string]interface{}{
   117  					"count": deployErrors,
   118  					"error": err.Error(),
   119  				}).Info("Deploying Orbiter failed, awaiting next iteration")
   120  			} else {
   121  				if oneoff {
   122  					monitor.Info("Deployed Orbiter takes over control")
   123  					finishedChan <- struct{}{}
   124  				}
   125  				deployErrors = 0
   126  			}
   127  			if deployErrors > 50 {
   128  				panic(err)
   129  			}
   130  		}
   131  
   132  		currentKind := "orbiter.caos.ch/KubernetesCluster"
   133  		current := &CurrentCluster{}
   134  		currentTree.Parsed = &Current{
   135  			Common:  *(tree.NewCommon(currentKind, "v0", false)),
   136  			Current: current,
   137  		}
   138  
   139  		return func(nodeAgentsCurrent *common.CurrentNodeAgents, nodeAgentsDesired *common.DesiredNodeAgents, providers map[string]interface{}) (orbiter.EnsureFunc, error) {
   140  				ensureFunc, err := query(
   141  					monitor,
   142  					clusterID,
   143  					desiredKind,
   144  					current,
   145  					providers,
   146  					nodeAgentsCurrent,
   147  					nodeAgentsDesired,
   148  					k8sClient,
   149  					oneoff,
   150  					gitClient,
   151  				)
   152  				if err != nil {
   153  					err = fmt.Errorf("querying %s failed: %w", desiredKind.Common.Kind, err)
   154  				}
   155  				return ensureFunc, err
   156  			}, func(delegate map[string]interface{}) error {
   157  				defer func() {
   158  					if err != nil {
   159  						err = fmt.Errorf("destroying %s failed: %w", desiredKind.Common.Kind, err)
   160  					}
   161  				}()
   162  
   163  				if k8sClient != nil {
   164  					volumes, err := k8sClient.ListPersistentVolumes()
   165  					if err != nil {
   166  						return err
   167  					}
   168  
   169  					volumeNames := make([]infra.Volume, len(volumes.Items))
   170  					for idx := range volumes.Items {
   171  						volumeNames[idx] = infra.Volume{Name: volumes.Items[idx].Name}
   172  					}
   173  					delegate[currentKind] = volumeNames
   174  				}
   175  
   176  				providers, err := destroyProviders(delegate)
   177  				if err != nil {
   178  					return err
   179  				}
   180  
   181  				desiredKind.Spec.Kubeconfig = nil
   182  
   183  				return destroy(providers, k8sClient)
   184  			},
   185  			orbiter.NoopConfigure,
   186  			migrate,
   187  			getSecretsMap(desiredKind),
   188  			nil
   189  	}
   190  }