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 }